5

我对下面的类型检查器的严格性感到有些困惑——似乎 的不变T位置在的参数列表Inv[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]]
                             ^

变体类型通常可以合法地出现在看起来像不变参数列表的位置,例如具有对象保护的可见性:

class Variantish[+T](protected[this] var v: Inv[T])

并且似乎以下内容与类型安全一样:

class Variantish[+T, +TVar <: Inv[T]](protected[this] var v: TVar)

上面提到的检查需要这么严格吗?

4

2 回答 2

1
于 2017-04-06T19:25:28.883 回答
0

我不太明白@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是有效的,因为Animal<:AnimalAnimalInv<:AnimalInv都是真的。

b无效,因为DogInv<:AnimalInv为假。

c是有效的,因为Dog<:AnimalAnimalInv<:AnimalInv都是真的。

d无效,因为DogInv<:AnimalInv为假。

因此,这些显示TVar不能是协变的。

即使在d动态类型有效的情况下,它也不是静态类型的子类型。

我怀疑如果我们查看了我们可能使用的所有地方,TVar那么Variantish它不需要是类型参数。正如@concat 指出的那样,您可能遇到的任何差异错误都可以通过使用受对象保护的访问修饰符来解决。

于 2017-10-11T21:34:27.600 回答