2015-05-19 49 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'。 –