[英]Why are all invariant generic class positions invariant in type parameter lists in Scala?
I'm a bit perplexed by the strictness of the typechecker below — it seems that the invariant T
position of Inv[T]
is also invariant within Variantish
's parameter list: 我对下面的类型检查器的严格性感到有点困惑 - 似乎
Inv[T]
的不变T
位置在Variantish
的参数列表中也是不变的:
scala> class Inv[T]
defined class Inv
scala> class Variantish[+T, +TVar <: Inv[T]]
<console>:12: error: covariant type T occurs in invariant position in type <: Inv[T] of type TVar
class Variantish[+T, +TVar <: Inv[T]]
^
Variant types can normally occur in what look like invariant argument-list positions legally, eg with object-protected visibility: 变体类型通常可以合法地出现在看似不变的参数列表位置,例如具有对象保护的可见性:
class Variantish[+T](protected[this] var v: Inv[T])
and it seems that the following would be just as typesafe: 并且似乎以下类似于类型安全:
class Variantish[+T, +TVar <: Inv[T]](protected[this] var v: TVar)
Need that check mentioned above be so strict? 需要上面提到的检查是如此严格?
From the language specification (emphasis mine), about conformance (ie T'
is a super-type of T
): 从语言规范 (重点煤矿),约一致性(即
T'
是一个超级型T
):
Type constructors
T
andT′
follow a similar discipline.类型构造函数
T
和T′
遵循类似的规则。 We characterizeT
andT′
by their type parameter clauses[a1,…,an]
and[a′1,…,a′n]
, where anai
ora′i
may include a variance annotation, a higher-order type parameter clause, and bounds.我们通过它们的类型参数子句
[a1,…,an]
和[a′1,…,a′n]
表征T
和T′
,其中ai
或a′i
可以包括方差注释,高阶类型参数条款和范围。 Then,T
conforms toT′
if any list[t1,…,tn]
-- with declared variances, bounds and higher-order type parameter clauses -- of valid type arguments forT′
is also a valid list of type arguments forT
andT[t1,…,tn]<:T′[t1,…,tn]
.然后,
T
符合T′
如果任何列表[t1,…,tn]
-以宣变化,边界和高阶类型参数子句-有效的类型参数T′
也是类型参数的有效列表T
和T[t1,…,tn]<:T′[t1,…,tn]
。
This is really difficult to understand (IMHO), but I believe it means that for Variantish
to be covariant in T
, you would have to be able to write 这真的很难理解(恕我直言),但我相信这意味着
Variantish
在T
是协变的,你必须能够写
Variantish[Dog, TVar] <: Variantish[Animal, TVar]
for any TVar
for which Variantish[Animal, TVar]
makes sense. 对于
Variantish[Animal, TVar]
有意义的任何 TVar
。 But this doesn't even make sense (let alone have any truth value) for some of those TVar
, such as Inv[Animal]
. 但对于一些
TVar
,这甚至没有意义(更不用说有任何真值),例如Inv[Animal]
。 That's why it is forbidden in that place. 这就是为什么它被禁止在那个地方。
I didn't quite understand @cyrille-corpet's answer so I expanded it with some examples. 我不太明白@ cyrille-corpet的回答所以我用一些例子扩展了它。
class Inv[T]
class Variantish[+T, +TVar <: Inv[T]]
trait Animal
class Dog extends Animal
class AnimalInv extends Inv[Animal]
class DogInv extends Inv[Dog]
val a: Variantish[Animal, Inv[Animal]] = new Variantish[Animal, AnimalInv]
val b: Variantish[Animal, Inv[Animal]] = new Variantish[Animal, DogInv]
val c: Variantish[Animal, Inv[Animal]] = new Variantish[Dog, AnimalInv]
val d: Variantish[Animal, Inv[Animal]] = new Variantish[Dog, DogInv]
a
is valid since Animal
<: Animal
and AnimalInv
<: AnimalInv
are both true. a
是有效的,因为Animal
<: Animal
和AnimalInv
<: AnimalInv
都是真的。
b
is invalid since DogInv
<: AnimalInv
is false. b
因为DogInv
<: AnimalInv
为false而无效。
c
is valid since Dog
<: Animal
and AnimalInv
<: AnimalInv
are both true. c
有效,因为Dog
<: Animal
and AnimalInv
<: AnimalInv
都是真的。
d
is invalid since DogInv
<: AnimalInv
is false. d
无效,因为DogInv
<: AnimalInv
为false。
So as these show TVar
cannot be covariant. 因此,这些显示
TVar
不能协变。
Even in the case of d
where the dynamic type is valid, it is not a subtype of the static type. 即使在动态类型有效的
d
的情况下,它也不是静态类型的子类型。
I suspect if we looked at all the places where we may be using TVar
in Variantish
then it doesn't need to be a type parameter. 我怀疑如果我们查看我们可能在
Variantish
使用TVar
所有地方,那么它不需要是类型参数。 As @concat pointed out any variance errors you may encounted can be solved by using the object-protected access modifier. 正如@concat指出的那样,您可以通过使用受对象保护的访问修饰符来解决任何方差错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.