我目前正在学习scala,我对方差注释特别是协方差和逆变感到困惑。
所以我做了一些研究,发现了下面的例子
class Box[+T] {
def put[U >: T](x: U): List[U] = {
List(x)
}
}
class Animal {
}
class Cat extends Animal {
}
class Dog extends Animal {
}
var sb: Box[Animal] = new Box[Cat];
所以这表示 Box 类在 T 中是协变的,这意味着 Box[Cat] 是 Box[Animal] 的子类,因为 Cat 是 Animal 的子类。到目前为止我明白这一点。但是当谈到方法参数时,我的理解就结束了。规范说方法参数不能是协变的,所以我们必须使用这个下限注释。
让我们看看方法定义
def put[U >: T](x: U): List[U] = {
List(x)
}
所以 [U >: T] 说 U 必须是 T 的超类
尝试以下代码
var sb: Box[Animal] = new Box[Cat];
sb.put(new Cat);
按预期工作,但这让我发疯
var sb: Box[Animal] = new Box[Cat];
sb.put(1);
从逻辑上讲,将INT放入 Box of Animals对我来说毫无意义,因为它是正确的,因为INT将被解析为Any,它是Animal的超类。
所以我的问题是
我如何调整put method
只接受动物子类型的代码?我不能使用上限注释
class Box[+T] {
def put[U <: T](x: U): List[U] = {
List(x)
}
}
因为我得到了这个众所周知的错误
协变类型 T 出现在类型中的逆变位置