我试图理解差异,在我买的这本书中,它解释如下:
·无注释参数FooA的A型在A中是不变的,这意味着无论B和C之间的亚型或超型关系如何,FooB与FooC之间都没有关系。·参数FooB的A型在A中是逆变的,如果C是B的超型,则FooC是FooB的子型。
我很难理解这句话:
If C is a supertype of B, Foo[C] is a subtype of Foo[B].为什么不:
Foo[C] is a supertype of Foo[B].C是一个超级类型的B,但是为什么C突然变成了B的子型呢?
发布于 2017-04-28 09:04:45
C是一个超级类型的B,但是为什么C突然变成了B的子型呢?
这就是反向方差的定义,它逆转了关系顺序(在我们的例子中,是关系<:的"is子类型“)。注意,C现在不是B的子类型,关系是固定的,而是C的容器,即Foo[C],现在是B,Foo[B],而不是直接B本身的容器的子类型。
反方差的典型例子是函数对象。Scala中的函数在参数类型中是反变体,在返回类型(即Function1[-T, +R] )中是协变函数。
让我们看看一个例子。假设我们有一个小ADT:
sealed trait Animal
case class Mouse() extends Animal
case class Lion() extends Animal现在我们要从Lion => String创建一个函数。我们能从Animal => String中提供一个具体的功能吗?
def main(args: Array[String]): Unit = {
val animalToString: (Animal) => String = an => an.toString
val lionToString: (Lion) => String = animalToString
lionToString(new Lion())
}这为什么要编译呢?因为当您使用lionToString调用Lion时,您肯定知道它将能够调用在Animal上定义的任何函数,因为Lion <: Animal。但事实并非如此。假设Function1在其参数类型中是协变的:
def main(args: Array[String]): Unit = {
val lionToString: (Lion) => String = an => an.toString
val animalToString: (Animal) => String = lionToString
lionToString(new Mouse()) // <-- This would blow up.
}这样,当我们的函数实际需要一个Animal时,我们就可以传递一个不同的Lion子类型。
https://stackoverflow.com/questions/43674447
复制相似问题