2012-09-05 63 views
3

,從而可以參照子類的類型更簡單的方法,這裏是一個有點做作的例子:試圖找到從特質

trait MyTrait { 
    type T <: MyTrait 
    val listOfT:List[T] 
    def getFirst:T 
    //def getOne:T = if(listOfT.length > 0) { getFirst } else { this } 
} 

class MyClass extends MyTrait { 
    type T = MyClass 
    override val listOfT:List[T] = List[MyClass](this) 
    override def getFirst:T = listOfT.head 
} 

排序的問題有兩個部分:

有一些其他的方式來在MyClass中的返回類型可以只是「MyClass」而不必指定「type T = MyClass」的情況下執行此操作嗎?基本上我希望能夠將這個特性添加到一個類中,而不必讓子類顯着改變它的實現,或者考慮類型系統......只返回它自己的成員,並且只要它具有該特性就可以接受在亞型上是協變的。這甚至有意義嗎?

在MyTrait,如果取消註釋,getOne方法將給出錯誤 「類型不匹配:」 實測值:MyTrait.this.type(與下面類型MyTrait)所需 :MyTrait.this.T

如果我要將返回類型更改爲this.type,我會得到相反的發現/必需的類型不匹配。任何一個返回值實際上都具有相同的類型(並且實際上是同一個對象)。

處理這類情況的正確方法是什麼?

回答

4

這是你想要的嗎?

trait MyTrait[T <: MyTrait[T]] { self: T => 
    val listOfT: List[T] 
    def getFirst: T 
    def getOne: T = if (listOfT.length > 0) getFirst else self 
} 

class MyClass extends MyTrait[MyClass] { 
    override val listOfT: List[MyClass] = List[MyClass](this) 
    override def getFirst: MyClass = listOfT.head 
} 

它擺脫的type T = MyClass(允許你只是把MyClass在返回類型)和修復的getOne定義編譯錯誤。

+0

嗯....是的工作,並解決了問題。有沒有辦法做到這一點,只是擴展MyTrait而不指定擴展MyTrait [MyClass]?在定義中重複子類的名字似乎有點奇怪,但這絕對比我如何處理它更簡單/更簡單。 – Brian

+0

MyClass擴展MyTrait [MyClass]實際上是一種相當常見的模式,在這種情況下,特徵的方法需要知道實現類。例如,參見Seq [+ A]在Scala標準庫中擴展了SeqLike [A,Seq [A]]。 – dhg

+0

hmm ....我只是注意到,現在如果在MyClass中我想調用getOne,我不能將結果賦給MyClass類型的變量,因爲它是MyTrait [MyClass]? – Brian