Scala下界与协方差
我正在阅读这一页,我了解协方差是什么,以及下限,但不清楚的是这一行: 不幸的是,这个程序没有编译,因为协方差 仅当类型变量仅在中使用时,才可以进行注释 协变位置。因为类型变量T显示为参数类型 对于方法prepend,此规则已被破坏 为什么Scala下界与协方差,scala,covariance,lower-bound,Scala,Covariance,Lower Bound,我正在阅读这一页,我了解协方差是什么,以及下限,但不清楚的是这一行: 不幸的是,这个程序没有编译,因为协方差 仅当类型变量仅在中使用时,才可以进行注释 协变位置。因为类型变量T显示为参数类型 对于方法prepend,此规则已被破坏 为什么elem必须是T的超类型的实例,如果ListNode已经是协变的,为什么elem不能在当前列表的前面 class Super {override def toString = "Super"} class Sub extends Supe
elem
必须是T
的超类型的实例,如果ListNode
已经是协变的,为什么elem
不能在当前列表的前面
class Super {override def toString = "Super"}
class Sub extends Super {override def toString = "Sub"; def subMethod {} }
val sup = new Super
val sub = new Sub
假设允许以下情况:
// invalid code
class Foo[+T] {
def bar(x: T) = println(x)
}
因为Foo
在T
上是协变的,所以这是有效的(一个简单的上溯,因为Foo[Sub]
是Foo[Super]
):
现在,据我们所知,foo
是一个foo[Super]
和任何其他方法一样,但是它的bar
方法不起作用,因为bar
实现需要一个子Sub
:
foo.bar(sup) // would cause error!
解释很简单。类型变量T显示为参数类型。这不是协变位置。这里到底是什么引起了问题?好吧,我明白了,从scala站点的“此程序不编译”这一行来看,这并不意味着我们实际上违反了这段特定代码中的某些内容,我们没有显式地对Foo[SomeClass]进行子类化,编译器只是为了防止潜在的运行时错误,我错了吗?你是对的,但这就像编译器应用任何其他静态类型规则一样,比如不允许对字符串调用List方法。如上所示,允许方法的参数为协变类型在逻辑上是不一致的,因此它不允许您这样做。
foo.bar(sup) // would cause error!