我有一个特性:
trait MyTrait extends (Int => MyTrait)
我如何限制在扩展中使用
MyTrait
只能是MyTrait
的任何实现?我有一个特性:
trait MyTrait extends (Int => MyTrait)
MyTrait
只能是MyTrait
的任何实现?Function
类型被标记为协变,用+R表示在Function1签名中:
trait Function1[-T1, +R] extends AnyRef
这意味着你已经是正确的了。将MyTrait
扩展为(Int=> MyTrait)
(与Function1[Int, MyTrait]
相同),这意味着任何扩展MyTrait
的类型都必须实现返回任何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 }
}
正如Dan所写的那样,普通情况下会返回MyTrait的任何实例。
如果你想限制它只返回当前对象类型的实例,可以这样做:
trait MyTrait[T <: MyTrait[T]] extends (Int => T)
然后当你实现它(从Dan复制)时
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 }
}
Baz
类也无法编译,因为 apply
必须返回一个 Baz
。 - Dan Gallagher
A :> B
因此X[A] :> X[B]
。协变是指它们在相反方向上变化:A :> B
因此X[B] :> X[A]
(注:在拉丁语和一些派生自拉丁语的语言中,“contra”意为“反对”)。 - dcastro