如果T
是协变或逆变,我可以确定以下方差:
K >: T
或
K <: T
我问这个是因为我在书中看到“scala编程”,它在代码中说:
trait Cat[T] {
def meow[K]
}
K
的位置是否定的,它必须是逆变的(让我们假设它不是非变量类型)。
由于我们不能仅使用单一类型K
声明协方差或逆变,我们必须使用上限或下限,因此K
可能是:
K >: T
或
K <: T
但我如何确定新类型是协变还是逆变?
答案 0 :(得分:4)
正如我在评论中已经指出的那样,类型方差只能与类型参数相关联。类型本身不是协变的或逆变的或不变的。由于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]
可以说,在更宽松的语音中,你可以说一个类型是*变体,如果它显然是一个容器类型并只采用一个类型参数,例如List[T]
;也就是说可以说List
是协变的,但这实际上扩展为“List[T]
与T
”相关的协变。
但是,如果K
确实出现在Cat
的类型参数列表中,则可以将Cat
声明为与K
相关的协变量将+
添加到K
:Cat[T, +K]
,这将由编译器允许,因为K
仅出现在Cat
正文中的差异中立位置:
def meow[K] // <-- meow doesn't take any parameters and returns `Unit`, so `K` is irrelevant with respect to variance
但是,如果您从K
返回meow
,则只能将Cat
标记为K
的不变量或协变量:
def meow: K // contravariance made impossible
相反,这:
def meow(x: K) // covariance made impossible
会强迫您使用Cat[T, -K]
(逆变)或Cat[T, K]
(不变)。
出于原因,无论是谷歌,还是看到我最近的答案@ why the first type parameter is defined as contravariant in Function1[-A, +B]?
答案 1 :(得分:1)
方法的类型参数,例如K
中的def meow[K]
,不能是共变量或逆变量。该概念只能应用于类型的类型参数。
由于我们不能仅用单一类型K声明协方差或逆变,我们必须使用上限或下限
这也没有意义。我们可以声明MyClass
中的K
是协变的,如下所示:
class MyClass[+K]
这与下限/上限完全无关:您可以使用带或不带限制的变体类型参数。
答案 2 :(得分:0)
两种方差:
class X1
class X2 extends X1
class X3 extends X2
1)声明网站差异:
// covariant type-constructor:
class Cat[+T]
var cat : Cat[X2] = new Cat[X2]
var cat = new Cat[X3]
// cat = new Cat[X1] // not compiled
2)使用场地方差(按上限或下限):
//covariant variable for invariant type constructor:
class Cat[T]
var cat : Cat[_ <: X2] = new Cat[X2]
cat = new Cat[X3]
// cat = new Cat[X1] // not compiled
在方法或变量声明中常用的类型构造函数(容器)声明和使用站点差异中使用的Decalration-site方差。