如果T是协变或逆变的,我可以确定以下变量的方差:

K >: T


要么

K <: T


我之所以这么问,是因为我在代码“ scala中编程”一书中看到:

trait Cat[T] {
   def meow[K]
}


K的位置为负,它必须是协变的(假设它不是非变量类型)。

由于我们不能仅使用单个类型K声明协方差或相反,因此我们必须使用上限或下限,因此K可能是:

K >: T


要么

K <: T


但是如何确定新类型是协变还是逆变的呢?

最佳答案

正如我在评论中已经指出的那样,只能针对类型参数谈论类型差异。类型本身不是协变的,也不是协变的或不变的。由于K没有出现在Cat的类型参数列表中,因此CatK无关。考虑:

trait Cat[T] {
  def meow[K]
}

class SiameseCat[T] extends Cat[T] {
  def meow[K] = println("loud meow")
}

class Foo
class Bar extends Foo
class Baz extends Bar

val barSiamese = new SiameseCat[Bar]

// COMPILATION ERROR: personality.analysis.demo.Bar <: personality.analysis.demo.Foo, but class SiameseCat is invariant in type T
val fooSiamese: SiameseCat[Foo] = barSiamese
// SAME
val bazSiamese: SiameseCat[Baz] = barSiamese

// NO ERROR
barSiamese.meow[Foo]
barSiamese.meow[Bar]
barSiamese.meow[Baz]
barSiamese.meow[Int]
barSiamese.meow[Unit]


可以说,在更松散的表述中,可以说一个类型是* variant,如果它显然是容器类型并且仅接受一个类型参数,例如List[T];即可以说List是协变的,但实际上它扩展为“ List[T]关于T是协变的”。

但是,如果K实际上确实出现在Cat的类型参数列表中,则可以通过在Cat之前添加K来声明+作为与K的协变。 cc>,这将被编译器所允许,因为Cat[T, +K]仅出现在K主体中与方差无关的位置:

def meow[K]  // <-- meow doesn't take any parameters and returns `Unit`, so `K` is irrelevant with respect to variance


但是,如果您要从Cat返回K,则只能将meow标记为相对于Cat不变或协变:

def meow: K  // contravariance made impossible


相反,这是:

def meow(x: K)  // covariance made impossible


会迫使您要么使用K(相反),要么只是使用Cat[T, -K](不变)。

由于这个原因,要么谷歌,要么看到我的最新答案@ why the first type parameter is defined as contravariant in Function1[-A, +B]?

关于scala - 如果“T”是协变还是协变,则“K>:T”和“K <:T”的方差是多少?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23366911/

10-12 22:56