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
val cb: C[B] = new C[B]
val ca : C[A] = cb
为了让这听起来像是一个问题,编译器限制了T在C中出现的位置。为了使它简短,并且稍微简化一下,v不能作为例程的参数(或变量的类型)出现。否则,在按照上述方法初始化cb和ca之后,您可以执行以下操作
ca.v = new A
这是允许的,因为ca
应该是aC[a]
,所以它的变量v
的类型是a
。然而,由于C在T中是协变的,ca
可以(并且在示例中确实)引用aC[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]