如何初始化协变变量



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

编译错误:协变类型T出现在值value_=

的T类型逆变位置

为什么?我怎样才能修好它?

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

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

在你的问题的"为什么"部分更详细一点,通过使T是+T的协变参数,你声明如果B是a的子类型,你希望C[B]是C[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],所以它的变量vA类型。然而,由于C在T中是协变的,ca可能(在本例中确实如此)引用C[B]实例。如果允许此赋值,则可以执行

val vInCb: B = cb.v

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

可以声明为private[this]:

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

如果您尝试使用此作用域不允许的任何用法,对于协变T来说都是不安全的。

你必须让它成为valvar总是有一个setter方法,当类型出现在逆变位置时

相关内容

  • 没有找到相关文章

最新更新