如果T是协变的或逆变的,我可以确定以下变量的方差:
K >: T或
K <: T我之所以这样问,是因为我在“在scala中编程”这本书中看到,在代码中:
trait Cat[T] {
def meow[K]
}K的位置是负的,它必须是逆变的(让我们假设它不是不变的类型)。
因为我们不能仅仅使用单个类型的K来声明协方差或逆方差,所以我们必须使用上界或下界,因此K可能是:
K >: T或
K <: T但是我如何确定新类型是协变的还是逆变的?
发布于 2014-04-29 22:53:19
正如我在评论中提到的,类型变量只能与类型参数相关。类型本身不是协变的,也不是逆变的,也不是不变的。由于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],那么你可以说它是*variant;例如,可以说List是协变的,但这实际上扩展到了"__List[T] is covariant to T__“。
但是,如果K确实出现在Cat的类型参数列表中,则可以通过将+前缀到K:Cat[T, +K]来将+声明为相对于K的协变,这将被编译器允许,因为K只出现在Cat主体中与方差无关的位置
def meow[K] // <-- meow doesn't take any parameters and returns `Unit`, so `K` is irrelevant with respect to variance但是,如果从meow返回K,则只能将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]?
发布于 2014-04-29 22:51:24
def meow[K]中的K等方法的类型参数不能是协变或逆变的。此概念仅适用于类型的类型参数。
因为我们不能仅仅用一个类型K来声明协方差或逆方差,我们必须使用上界或下界
这也是没有意义的。我们可以这样声明MyClass在K中是协变的:
class MyClass[+K]这与下限/上限完全无关:您可以有一个有或没有界限的变量类型参数。
发布于 2014-04-30 13:50:24
以下两种类型的方差:
class X1
class X2 extends X1
class X3 extends X21)声明-站点差异:
// covariant type-constructor:
class Cat[+T]
var cat : Cat[X2] = new Cat[X2]
var cat = new Cat[X3]
// cat = new Cat[X1] // not compiled2)使用-site方差(由上限或下限限制):
//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在类型构造函数(容器)声明中使用的站点差异,以及在方法或变量声明中常用的使用站点差异。
https://stackoverflow.com/questions/23366911
复制相似问题