Scala 如何初始化协变变量?

Scala 如何初始化协变变量?,scala,covariance,Scala,Covariance,C类[+T]{ 变量v:T=_ } 编译器错误:协变类型T出现在值的类型T的逆变位置_= 为什么??如何修复它?您必须将其设置为val。var始终有一个setter方法,其中类型显示在逆变位置。您不能有协变类型的var。 var相当于拥有公共的def v_=(newV:T),因此它使T显示为一个常规参数,这是一个逆变位置。所以你要么 放弃协方差并声明C[T]而不是C[+T] 使v成为val 为了更详细地说明问题的“为什么”部分,通过将T设为+T的协变参数,您声明如果B是a的子类型,您希望C

C类[+T]{
变量v:T=_
}

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


为什么??如何修复它?

您必须将其设置为
val
var
始终有一个setter方法,其中类型显示在逆变位置。

您不能有协变类型的var。 var相当于拥有公共的
def v_=(newV:T)
,因此它使T显示为一个常规参数,这是一个逆变位置。所以你要么

  • 放弃协方差并声明C[T]而不是C[+T]
  • 使v成为val
为了更详细地说明问题的“为什么”部分,通过将T设为+T的协变参数,您声明如果B是a的子类型,您希望C[B]成为C[a]的子类型。这意味着您希望允许:

val cb: C[B] = new C[B]
val ca : C[A] = cb    
为了让这听起来像是一个问题,编译器限制了T在C中出现的位置。为了使它简短,并且稍微简化一下,v不能作为例程的参数(或变量的类型)出现。否则,在按照上述方法初始化cb和ca之后,您可以执行以下操作

ca.v = new A
这是允许的,因为
ca
应该是a
C[a]
,所以它的变量
v
的类型是
a
。然而,由于C在T中是协变的,
ca
可以(并且在示例中确实)引用a
C[B]
实例。这项任务是否被允许,你可以这样做

val vInCb: B = cb.v

确信这会给你一个B。但是,您只需通过
ca
引用将A放在那里。必须禁止这种情况,并且禁止协变类型参数T作为变量的类型。

您可以将其声明为
private[This]

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

如果您尝试使用此范围不允许的任何用法,那么使用co variant
T

将是不安全的。非常感谢Daniel,我已经用private编写了第三个variant,并在测试后将其删除,我忘记了[this]