2010-01-13 24 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 
}