嗨,我正在尝试了解 Scala。
我指的是API,发现语法不熟悉
http://www.scala-lang.org/api/current/#scala.actors.CanReply
trait CanReply[-T, +R] extends AnyRef
abstract type Future[+P] <: () ⇒ P
T 和 R 前面的 + 和 - 是什么意思?
嗨,我正在尝试了解 Scala。
我指的是API,发现语法不熟悉
http://www.scala-lang.org/api/current/#scala.actors.CanReply
trait CanReply[-T, +R] extends AnyRef
abstract type Future[+P] <: () ⇒ P
T 和 R 前面的 + 和 - 是什么意思?
它们表示协变和逆变,参见http://debasishg.blogspot.ch/2006/04/generics-in-scala-part-1_12.html
具体来说,引用:
类定义的类型参数中的 + 表示子类型在该类型参数上是协变的。A - 在同一个地方将关系更改为逆变。默认(没有任何前缀)声明表示子类型的不变性。
一个简短(不完整)的答案,无需详细说明:
它们指定类型参数和继承关系之间的关系。
+
表示 ifT
是一个子类S
thenClass[T]
是一个子类Class[S]
-
表示 ifS
是一个子类T
thenClass[T]
是一个子类Class[S]
Class t
如果两者都不存在,则和之间将不存在继承关系Class s
如果您熟悉 Java,那么您就会知道第三种情况是每个带有类型参数的 Java 类。List<T>
(和之间没有关系List<S>
,即使T
是 的子类S
)
我同意这里的答案,只是想展示一些例子。通过[-T, +R]
协方差和反方差,您可以执行以下操作:
class A
class B extends A
class C extends B
trait CanReply[-T, +R] {
def foo(r: T): R
}
class CR1 extends CanReply[B, B] {
def foo(r: B): B = {
println("arg of type [" + r.getClass() + "] for B in CR1")
new B
}
}
class CR2 extends CanReply[A, C] {
def foo(r: A): C = {
println("arg of type [" + r.getClass() + "] for A in CR2")
new C
}
}
class CR3 extends CanReply[C, A] {
def foo(r: C): A = {
println("arg of type [" + r.getClass() + "] for C in CR3")
new A
}
}
object Program {
def main(args: Array[String]): Unit = {
test(new CR1)
test(new CR2)
test(new CR3)
}
def test(cr: CanReply[C, A]): Unit = {
val res: A = cr.foo(new C)
println("result of type [" + res.getClass() + "]")
println()
}
}
将产生:
arg of type [class C] for B in CR1
result of type [class B]
arg of type [class C] for A in CR2
result of type [class C]
arg of type [class C] for C in CR3
result of type [class A]
因此,对于反方差,您可以将任何基类对象放置在期望派生的位置,反之亦然,对于协方差,您可以将任何派生类对象放置在期望基类的位置。通常方法参数是反变的,它们的返回类型是协变的。