我在 Scala 中有以下类/特征
trait Write[-T] {
def add(elem : T);
}
class ContraListWrapper[T] (var list : List[T]) extends Write[T] {
def add(elem : T) = {
list = elem :: list
}
}
def bar(list : Write[Number]) = {}
由于 Write trait 的逆变性,使用对象列表或数字列表调用方法是可行的。
var list : List[Number] = Nil;
var wlist = new ContraListWrapper(list);
bar(wlist);
var list : List[Object] = Nil;
var wlist = new ContraListWrapper(list);
bar(wlist);
当我使用整数列表调用 bar 时,我在 Scala 中收到编译错误。这是意料之中的;整数不是 Number 的超类型(而是子类型)
var list : List[Integer ] = new Integer(1) :: Nil;
var wlist = new ContraListWrapper(list);
bar(wlist); //error: type mismatch;
//found : contra.this.ContraListWrapper[Integer]
//required: contra.this.Write[Number]
但是当我内联 Integer 列表的变量声明时,编译错误消失了,它甚至似乎工作。(我可以将元素添加到方法栏中的列表中)
var list : List[Integer] = new Integer(1) :: Nil;
bar(new ContraListWrapper(list)); //no compile- nor runtime error
编辑:以粗体回答 Rex Kerr
1)这怎么可能?选择第一个类型 Integer,内联 Number
2)为什么没有内联就不是这种情况?Scala 可以采用适当的类型
3) 为什么我不会得到运行时错误?因为列表是协变的
附言。我知道我可以在没有特征和包装的情况下获得逆变,并且有界限。