2015-05-19 38 views

回答

8

在Scala中,由+ R的功能1簽名表示的Function類型的協變:

trait Function1[-T1, +R] extends AnyRef

這意味着你有什麼是正確的了。具有MyTrait延伸(Int => MyTrait)(這是一樣的Function1[Int, MyTrait)表示延伸MyTrait將具有任何類型來實施apply函數,返回的MyTrait任何實例。

下面將根據您當前MyTrait簽名都是合法的:

class Foo extends MyTrait { 
    def apply(x: Int): Foo = new Foo 
} 

class Bar extends MyTrait { 
    def apply(x: Int): Foo = new Foo 
} 

class Baz extends MyTrait { 
    def apply(x: Int): MyTrait = new MyTrait { def apply(y: Int) = new Baz } 
} 
+1

trait MyTrait[T <: MyTrait[T]] extends (Int => T) 

,然後你的意思是@dcastro協變 – dcastro

+1

感謝。答案已更新。其中一天,我會得到協變與直接逆變。 –

+3

哈哈我知道,對吧?下面是如何存儲它:*共*變體是當這兩種類型的在同一方向上變化:'A:> B'因此'X [A]:> X [B]'。 * *魂鬥羅變體是當它們在相反的方向上有所不同:'A:> B'因此'X [B]:> X [A]'(注:在拉丁美洲和一些拉丁衍生語言,[ 「反向」 是指「對「(http://en.wikipedia.org/wiki/Contra)) – dcastro

4

由於丹寫的正常行爲是返回MyTrait的任何實例。

如果你想限制它只能返回你可以這樣做,當前對象的類型的實例:當您實現(從丹複製)

class Foo extends MyTrait[Foo] { 
    def apply(x: Int): Foo = new Foo 
} 

class Bar extends MyTrait[Bar] { 
    def apply(x: Int): Foo = new Foo //Compile error 
} 

class Baz extends MyTrait[Baz] { 
    def apply(x: Int): MyTrait = new MyTrait { def apply(y: Int) = new Baz } 
} 
+3

這就是所謂的‘F-界多態性’ – Daenyth

+2

我真的很喜歡這種模式,並發現它是非常有用的。只是一個小紙條,我想'Baz'類也不能編譯,因爲'apply'必須返回一個'Baz'。 –