gpt4 book ai didi

generics - 在scala中混合类型参数和抽象类型

转载 作者:行者123 更新时间:2023-12-04 03:41:25 27 4
gpt4 key购买 nike

我正在尝试使用 a preceding question 的答案实现一个小型图形库。这个想法是将图视为集合,其中顶点包装集合元素。

我想使用抽象类型来表示 Vertex 和 Edge 类型(因为类型安全),我想使用类型参数来表示集合元素的类型(因为我想在实例化时轻松定义它们)。

但是,在尝试我能想到的最基本示例时,我遇到了编译错误。这是示例:

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] 我只会得到第一个错误。

你有什么想法吗?

最佳答案

-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]{

好的,上课 GraphKindT 参数化并输入 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]
}

请注意,这与您编写的内容完全相同。我只是为类型参数使用不同的名称,以免与 T 混淆。即参数化 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 + ")"
}
}

由于 VertexGraph将绑定(bind)到 GraphKind 的一个实例,然后 T将固定为为该实例定义的任何内容。例如:
scala> new SimpleGraphKind[Int]
res0: SimpleGraphKind[Int] = SimpleGraphKind@1dd0fe7

scala> new res0.GraphImpl
res1: res0.GraphImpl = line10()

scala> res1.add(10)

scala> res1.add("abc")
<console>:9: error: type mismatch;
found : java.lang.String("abc")
required: Int
res1.add("abc")
^

关于generics - 在scala中混合类型参数和抽象类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2066835/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com