如何初始化协变变量?

ras*_*rra 10 scala covariance

class C [+T] { var v : T = _ }

编译器错误:协变类型T出现在值value_ =的类型T中的逆变位置

为什么?我该怎么解决?

Did*_*ont 18

你不能有一个协变类型的var.def v_=(newV: T)变量等于公共等等,因此它使T看起来是一个常规参数,这是一个逆变位置.所以你必须要么

  • 放弃协方差并声明C [T]而不是C [+ T]
  • 使va val

为了使你的问题的"为什么"部分更加冗长,通过使T是带有+ T的协变参数,如果B是A的子类型,则表明你希望C [B]为C [A]的子类型这意味着你想要允许:

val cb: C[B] = new C[B]
val ca : C[A] = cb    
Run Code Online (Sandbox Code Playgroud)

为了发出这种声音,编译器限制了T可能出现在C中的位置.为了简化并简化了一些简化,v不能作为例程的参数(或var的类型)出现.否则,在你如上所述初始化cb和ca后,你就可以了

ca.v = new A
Run Code Online (Sandbox Code Playgroud)

这将是允许的,因为ca它应该是a C[A],所以它的变量v是类型的A.但是,由于C在T中是协变的,因此ca可以(并且在示例中)引用C[B]实例.如果允许这项任务,你可以这样做

val vInCb: B = cb.v
Run Code Online (Sandbox Code Playgroud)

相信,这给你一个.但是,你只需在参考文献中添加一个A. ca必须禁止这种情况,并且禁止协变类型参数T作为var的类型.


Dan*_*ral 11

您可以将其声明为private[this]:

class C [+T] { private[this] var v : T = _ }
Run Code Online (Sandbox Code Playgroud)

您尝试此范围不允许的任何使用对于共变体都是不安全的T.