我正在尝试定义一个通用容器,其元素可以返回封闭容器。类似的东西:
abstract class Container[E <: Element] { // compile error
def contains( e: E ): Boolean
def addNewElement(): Unit
}
abstract class Element[C <: Container] { // compile error
def enclosingContainer(): C
}
class MyContainer extends Container[MyElement] {
private var elements = List[MyElement]()
override def contains( elem: MyElement ) = elements.contains( elem )
override def addNewElement() { elements ::= new MyElement(this) }
}
class MyElement( container: MyContainer ) extends Element[MyContainer] {
override val enclosingContainer = container
}
但是,该代码段无法编译,因为我应该在Element
定义中为abstract class Container[E <: Element]
提供一个类型参数,并在Container
定义中为abstract class Element[C <: Container]
提供类型。
我有办法实现我正在寻找的行为吗? Container
和Element
是否有适当的声明?我应该定义第三方对象吗?
答案 0 :(得分:6)
abstract class Container[E <: Element[_]] {
def contains( e: E ): Boolean
def addNewElement(): Unit
}
abstract class Element[C <: Container[_]] {
def enclosingContainer(): C
}
class MyContainer extends Container[MyElement] {
private var elements = List[MyElement]()
override def contains( elem: MyElement ) = elements.contains( elem )
override def addNewElement() { elements ::= new MyElement(this) }
}
class MyElement( container: MyContainer ) extends Element[MyContainer] {
override val enclosingContainer = container
}
答案 1 :(得分:6)
已经给出的其他解决方案无法强制类型匹配:即,给定类型ContainerImpl extends Container
,您应该确保ContainerImpl.E.C
应该是ContainerImpl
而不是其他容器。这是一个强制执行此操作(改编自http://programming-scala.labs.oreilly.com/ch13.html):
abstract class ContainerWithElement {
type C <: Container
type E <: Element
trait Container {
self: C =>
def contains( e: E ): Boolean
def addNewElement(): Unit
}
trait Element {
self: E =>
def enclosingContainer(): C
}
}
答案 2 :(得分:5)
使用类型成员而不是类型参数可以避免此问题:
abstract class Container { // compile error
type E <: Element
def contains( e: E ): Boolean
def addNewElement(): Unit
}
abstract class Element { // compile error
type C <: Container
def enclosingContainer(): C
}
class MyContainer extends Container {
type E = MyElement
private var elements = List[MyElement]()
override def contains( elem: MyElement ) = elements.contains( elem )
override def addNewElement() { elements ::= new MyElement(this) }
}
class MyElement( container: MyContainer ) extends Element {
type C = MyContainer
override val enclosingContainer = container
}