如果T
是协变或逆变的,我可以确定以下变量的方差:
K >: T
要么
K <: T
我之所以这么问,是因为我在代码“ scala中编程”一书中看到:
trait Cat[T] {
def meow[K]
}
K
的位置为负,它必须是协变的(假设它不是非变量类型)。由于我们不能仅使用单个类型
K
声明协方差或相反,因此我们必须使用上限或下限,因此K
可能是:K >: T
要么
K <: T
但是如何确定新类型是协变还是逆变的呢?
最佳答案
正如我在评论中已经指出的那样,只能针对类型参数谈论类型差异。类型本身不是协变的,也不是协变的或不变的。由于K
没有出现在Cat
的类型参数列表中,因此Cat
与K
无关。考虑:
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/