如何初始化协变变量?

发布于 2024-12-20 16:04:14 字数 116 浏览 2 评论 0原文

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

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

为什么?我该如何修复它?

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

compiler error: covariant type T occurs in contravariant position in type T of value value_=

why? how can I fix it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

注定孤独终老 2024-12-27 16:04:14

您不能拥有协变类型的 var。
var 相当于拥有一个 public def v_=(newV: T) ,因此它使 T 作为例程参数出现,这是一个逆变位置。因此,您必须

  • 放弃协变并声明 C[T] 而不是 C[+T]
  • make va val

为了对问题的“为什么”部分更详细一点,通过使 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],因此它的变量 v 的类型为 A。然而,由于 C 在 T 中是协变的,ca 可以(并且在示例中)引用 C[B] 实例。如果允许进行此作业,您就可以

val vInCb: B = cb.v

确信这会给您带来B。但是,您只需通过 ca 引用放置一个 A 即可。这种情况必须被禁止,方法就是禁止协变类型参数 T 作为 var 的类型。

You cannot have a var of a covariant type.
A var amounts to having, among other things, a public def v_=(newV: T), so it makes T appears as a routine argument, which is a contravariant position. So you must either

  • renounce covariance and declare C[T] rather than C[+T]
  • make v a val

To be a little more verbose on the "why" part of your question, by making T is covariant parameter with +T, you states that you wants C[B] to a a subtype of C[A] if B is a subtype of A. This means you want to allows :

val cb: C[B] = new C[B]
val ca : C[A] = cb    

To makes this sounds, the compiler restricts where T may appear in C. To make it short and with minor simplifications, v cannot appear as parameter of a routine (or as the type of a var). Otherwise, after you have initialized cb and ca as described above you coulddo

ca.v = new A

This would be allowed, as ca is supposed to be a C[A], so its variable v is of type A. However, as C is covariant in T, ca may (and does in the example) reference a C[B] instance. Would this assignment be allowed, you could then do

val vInCb: B = cb.v

confident that this gives you a B. However, you just put an A there through the ca reference. This situation must be forbidden, and it is, by forbidding covariant type parameter T as the type of a var.

执笔绘流年 2024-12-27 16:04:14

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

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

您尝试此范围不允许的任何用法对于协变体 T 都是不安全的。

You can declare it as private[this]:

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

Any usage you try that this scope does not allow would be unsafe with a co-variant T.

过去的过去 2024-12-27 16:04:14

您必须将其设为valvar 总是有一个 setter 方法,其中类型出现在逆变位置。

You have to make it a val. A var always has a setter method where the type appears in contravariant position.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文