问题描述
abstract class Bhanu[-A] { val m:List[A] }
给予
error: contravariant type A occurs in covariant position in type => List[A] of value m
abstract class Bhanu[-A] { val m:List[A] }
而
abstract class Bhanu[+A] { val m:List[A] }
给予
defined class Bhanu
对于为什么它因逆方差而失败而对于协方差却成功的原因,我无法全神贯注.
I am not able to wrap my head around this concept as to why it fails for contravariance whereas it succeeds for covariance.
第二(从其他示例中)
该陈述的确切含义是什么?
What does the statement exactly mean?
Function1[Sport,Int] <: Function1[Tennis,Int] since Tennis <: Sport
对我来说似乎违反直觉,不是吗?
It seems counter-intuitive to me, Shouldn't it be the following?
Function1[Tennis,Int] <: Function1[Sport,Int] since Tennis <: Sport
推荐答案
让我们看一下您提到的第一个示例.考虑我们有:
Let's look on the first example you mentioned.Consider we have:
class Fruit
class Apple extends Fruit
class Banana extends Fruit
class Bhanu[-A](val m: List[A]) // abstract removed for simplicity
由于 Bhanu
与 Bhanu [Fruit]< ;: Bhanu [Apple]
相反,所以您可以执行以下操作:
Since Bhanu
is contravatiant Bhanu[Fruit] <: Bhanu[Apple]
so you can do the following:
val listOfApples = new List[Apple](...)
val listOfFruits = listOfApples // Since Lists are covariant in Scala
val a: Bhanu[Fruit] = new Bhanu[Fruit](listOfFruits)
val b: Bhanu[Banana] = a // Since we assume Bhanu is contravariant
val listOfBananas: List[Banana] = b.m
val banana: Banana = listOfBananas(0) // TYPE ERROR! Here object of type Banana is initialized
// with object of type Apple
因此,Scala编译器通过限制在协变位置使用协变类型参数来保护我们免受此类错误的侵害.
So Scala compiler protects us from such errors by restriction to use contravariant type parameters in covariant position.
对于第二个问题,让我们也看一下示例.考虑我们有功能:
For your second question let's also look at the example. Consider we have function:
val func1: Function1[Tennis,Int] = ...
如果 Function1 [Tennis,Int]< ;: Function1 [Sport,Int]
,其中 Tennis< ;: Sport
如您所建议,那么我们可以执行以下操作:
If Function1[Tennis,Int] <: Function1[Sport,Int]
where Tennis <: Sport
as you proposed than we can do the following:
val func2: Function1[Sport,Int] = func1
val result: Int = func2(new Swimming(...)) // TYPE ERROR! Since func1 has argument
// of type Tennis.
但是,如果我们使 Function1
的参数相反,则 Function1 [Sport,Int]< ;: Function1 [Tennis,Int]
其中, Tennis< ;:运动
比:
But if we make Function1
contravariant in its argument so Function1[Sport,Int] <: Function1[Tennis,Int]
where Tennis <: Sport
than:
val func1: Function1[Tennis,Int] = ...
val func2: Function1[Sport,Int] = func1 // COMPILE TIME ERROR!
对于相反的情况,一切都很好:
and everything is fine for the reverse case:
val func1: Function1[Sport,Int] = ...
val func2: Function1[Tennis,Int] = func1 // OK!
val result1: Int = func1(new Tennis(...)) // OK!
val result2: Int = func2(new Tennis(...)) // OK!
函数的参数类型必须是协变的,而结果类型必须是协变的:
Functions must be contravariant in their argument type and covariant in result type:
trait Function1[-T, +U] {
def apply(x: T): U
}
这篇关于Scala中的协方差和协方差的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!