答案 0 :(得分:7)
所以,让我们从一个激励性的例子开始吧。假设我写了以下内容:
class Foo[+A] {
def foo(a : A) = ???
}
现在,通过使用A
注释类型参数+
,我已声明Foo
中的A
是协变的,也就是说,如果X <: Y
,然后是Foo[X] <: Foo[Y]
。所以,假设我有这样的Foo[X]
,我尝试将其传递给需要Foo[Y]
的函数:
def bar(a : Y, x : Foo[Y]) = {
x.foo(a)
}
现在,bar
尝试使用x.foo
致电Y
。但是x
是Foo[X]
,X
是Y
的子类型 - 所以它就像尝试将Object
传递给需要的函数一样String
- Object
无法保证Foo
包含执行此操作所需的所有内容。因此上面A
的定义无效 - 要在规范中使用术语,类型参数Foo
是协变的,但您已尝试在逆变位置中使用它/ em> - 作为函数的参数。
您引用的Scala规范中规定的规则集是Scala编译器用来确定代码中不同位置的方差位置的规则,它使用检查您是否还没有完成上述class Foo[A, B] {
def foo(a : A) = {
def bar(b : B) = ???
}
}
的定义。您标识的特定子句给出了与上面示例相对应的规则 - 它表示参数子句的方差位置(例如,在函数的参数列表中)与周围的方差位置相反。
通常,这意味着参数子句是逆变的。然而,事情可以多次倒转:
foo
这里,bar
的参数子句是逆变的,因此class Foo[-A, +B] {
def foo(a : A) = {
def bar(b : B) = ???
}
}
的参数子句再次被反转,并且是协变的。所以以下定义是有效的:
{{1}}