2010-01-13 34 views
4

我想定义一个通用容器,其元素可以返回封闭容器。喜欢的东西:scala中的循环类型参数定义

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 
} 

但是,这种片段不编译,因为我应该在abstract class Container[E <: Element]定义,并在abstract class Element[C <: Container]定义一个类型Container给一个类型参数Element

我有一种方法来实现我正在寻找的行为?是否有适当的声明ContainerElement?我应该定义第三方对象吗?

+0

粗略的估计,因为我无法打开我的编译器在一分钟,但你试过'抽象类要素[C <:容器[元] '或类似的东西? – wheaties 2010-01-13 19:43:43

+0

是的,但是'Element'也需要一个参数类型... – paradigmatic 2010-01-13 19:46:31

+0

不应该'addNewElement()'带一个元素来添加?那就是'addNewElement(e:E)'? – 2010-01-13 22:54:34

回答

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 
    } 
} 
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 
} 
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 
}