class C [+T] {
var v : T = _
}
编译器错误:协变类型T出现在值值为_ =
的类型T的逆变位置为什么呢?我该如何解决?
答案 0 :(得分:17)
您不能拥有协变类型的var。
变量等于公共def v_=(newV: T)
,因此它使T看起来是一个常规参数,这是一个逆变位置。所以你必须
要对你的问题的“为什么”部分稍微冗长一点,通过使T是带有+ T的协变参数,如果B是a,则表明你希望C [B]为C [A]的子类型A的子类型。这意味着你想允许:
val cb: C[B] = new C[B]
val ca : C[A] = cb
为了发出这种声音,编译器会限制T在C中出现的位置。为了使其简短并且稍作简化,v不能作为例程的参数(或var的类型)出现。否则,在如上所述初始化cb和ca后,你可以
ca.v = new A
这是允许的,因为ca
应该是C[A]
,因此其变量v
的类型为A
。但是,由于C在T中是协变的,ca
可以(并且在示例中)引用C[B]
实例。如果允许这个任务,你可以做
val vInCb: B = cb.v
相信这会给你一个 B 。但是,您只需通过ca
引用添加 A 。必须禁止这种情况,并且禁止将协变类型参数T作为var的类型。
答案 1 :(得分:10)
您可以将其声明为private[this]
:
class C [+T] { private[this] var v : T = _ }
您尝试此范围不允许使用的任何用法都会因共变T
而不安全。
答案 2 :(得分:2)
您必须将其设为val
。 var
总是有一个setter方法,其中类型出现在逆变位置。