我正在尝试使用a preceding question的答案来实现一个小图库。我们的想法是将图形视为一种选择,其中顶点包装集合元素。
我想使用抽象类型来表示Vertex和Edge类型(因为类型安全),我想使用类型参数来表示集合元素的类型(因为我想在实例化时轻松定义它们)。 / p>
但是,在尝试我能想到的最基本的例子时,我遇到了编译错误。这是一个例子:
package graph
abstract class GraphKind[T] {
type V <: Vertex[T]
type G <: Graph[T]
def newGraph(): G
abstract class Graph[T] extends Collection[T]{
self: G =>
def vertices(): List[V]
def add(t: T): Unit
def size(): Int
def elements(): Iterator[T]
}
trait Vertex[T] {
self: V =>
def graph(): G
def value(): T
}
}
以下是基本实现:
class SimpleGraphKind[T] extends GraphKind[T] {
type G = GraphImpl[T]
type V = VertexImpl[T]
def newGraph() = new GraphImpl[T]
class GraphImpl[T] extends Graph[T] {
private var vertices_ = List[V]()
def vertices = vertices_
def add( t: T ) { vertices_ ::= new VertexImpl[T](t,this) }
def size() = vertices_.size
def elements() = vertices.map( _.value ).elements
}
class VertexImpl[T](val value: T, val graph: GraphImpl[T]) extends Vertex[T] {
override lazy val toString = "Vertex(" + value.toString + ")"
}
}
在尝试编译时,我得到:
/prg/ScalaGraph/study/Graph.scala:10: error: illegal inheritance;
self-type GraphKind.this.G does not conform to Collection[T]'s selftype Collection[T]
abstract class Graph[T] extends Collection[T]{
^
/prg/ScalaGraph/study/Graph.scala:33: error: illegal inheritance;
self-type SimpleGraphKind.this.GraphImpl[T] does not conform to SimpleGraphKind.this.Graph[T]'s selftype SimpleGraphKind.this.G
class GraphImpl[T] extends Graph[T] {
^
/prg/ScalaGraph/study/Graph.scala:36: error: type mismatch;
found : SimpleGraphKind.this.VertexImpl[T]
required: SimpleGraphKind.this.V
def add( t: T ) { vertices_ ::= new VertexImpl[T](t,this) }
^
/prg/ScalaGraph/study/Graph.scala:38: error: type mismatch;
found : Iterator[T(in class SimpleGraphKind)]
required: Iterator[T(in class GraphImpl)]
def elements() = vertices.map( _.value ).elements
^
/prg/ScalaGraph/study/Graph.scala:41: error: illegal inheritance;
self-type SimpleGraphKind.this.VertexImpl[T] does not conform to SimpleGraphKind.this.Vertex[T]'s selftype SimpleGraphKind.this.V
class VertexImpl[T](val value: T, val graph: GraphImpl[T]) extends Vertex[T] {
^
5 errors found
我完全不知道这些错误的含义......但是,如果我在实现中专门化了类型T(class SimpleGraphKind extends GraphKind[Int]
我只得到第一个错误。
你有什么想法吗?
答案 0 :(得分:11)
使用-explaintypes
进行编译会产生:
<console>:11: error: illegal inheritance;
self-type GraphKind.this.G does not conform to Collection[T]'s selftype Collection[T]
abstract class Graph[T] extends Collection[T]{
^
GraphKind.this.G <: Collection[T]?
Iterable[T] <: Iterable[T]?
T <: T?
T <: Nothing?
<notype> <: Nothing?
false
Any <: Nothing?
<notype> <: Nothing?
false
false
false
Any <: T?
Any <: Nothing?
<notype> <: Nothing?
false
false
false
false
false
GraphKind.this.Graph[T] <: Iterable[T]?
Iterable[T] <: Iterable[T]?
T <: T?
T <: Nothing?
<notype> <: Nothing?
false
Any <: Nothing?
<notype> <: Nothing?
false
false
false
Any <: T?
Any <: Nothing?
<notype> <: Nothing?
false
false
false
false
false
false
false
现在,我正要写我不明白T <: T
怎么可能是假的 - 这几乎就像T
被定义了两次,当然,是整个问题。这里:
abstract class GraphKind[T] {
type V <: Vertex[T]
type G <: Graph[T]
def newGraph(): G
abstract class Graph[T] extends Collection[T]{
好的,课程GraphKind
参数化为T
,类型G
必须为Graph[T]
。现在,类Graph
也被参数化,其参数也称为T
。为了防止混淆,让我们重写它:
abstract class Graph[T2] extends Collection[T2]{
self: G =>
def vertices(): List[V]
def add(t: T2): Unit
def size(): Int
def elements(): Iterator[T2]
}
请注意,这与您所写的完全相同。我只是为type参数使用了不同的名称,因此不会与参数化T
的{{1}}混淆。
所以,这是逻辑:
GraphKind
暗示
G <: Graph[T]
Graph[T2] <: Collection[T2]
Graph[T2] <: G // self type
并且,因为Graph[T2] <: Graph[T]
扩展了Graph
:
Collection
但不能保证这是真的。我不明白为什么在没有继承时问题不会出现。修正:
Collection[T2] <: Collection[T]
由于abstract class GraphKind[T] {
type V <: Vertex
type G <: Graph
def newGraph(): G
abstract class Graph extends Collection[T]{
self: G =>
def vertices(): List[V]
def add(t: T): Unit
def size(): Int
def elements(): Iterator[T]
}
trait Vertex {
self: V =>
def graph(): G
def value(): T
}
}
class SimpleGraphKind[T] extends GraphKind[T] {
type G = GraphImpl
type V = VertexImpl
def newGraph() = new GraphImpl
class GraphImpl extends Graph {
private var vertices_ = List[V]()
def vertices = vertices_
def add( t: T ) { vertices_ ::= new VertexImpl(t,this) }
override def size() = vertices_.size
override def elements() = vertices.map( _.value ).elements
}
class VertexImpl(val value: T, val graph: GraphImpl) extends Vertex {
override lazy val toString = "Vertex(" + value.toString + ")"
}
}
和Vertex
将绑定到Graph
的一个实例,因此GraphKind
将固定为为该实例定义的任何内容。例如:
T
答案 1 :(得分:1)
似乎Vertex属于特定图形而且只有该图形可以在图形中具有嵌套顶点特征的类型系统中表现得最好。你想要实现的目标是否满足以下结构?
abstract class Graph[T] extends Collection[T] {
thisGraph: Graph[T] =>
def newGraph: Graph[T]
def vertices: List[Vertex[T]]
def add(t: T): Unit
def size: Int
def elements: Iterator[T]
trait Vertex[T] {
def graph = thisGraph
def value: T
}
}
class SimpleGraph[T] extends Graph[T] {
private[this] var verts = List[Vertex[T]]()
def newGraph = new SimpleGraph[T]
def vertices = verts
def add(t: T) { verts ::= SimpleVertex(t) }
override def size = verts.size
override def elements = verts.map(_.value).elements
def iterator = elements // the "new" elements in 2.8
case class SimpleVertex[T](value: T) extends Vertex[T]
}