行val a: Set[Fruit]=Set[Apple]
无法编译,为什么?
如何解决这个问题?
package sandbox.stackOverFlow
class Fruit
class Apple extends Fruit
class Banana extends Fruit
class Why{
val a:Set[Fruit]=Set[Apple]() // Does not compile, why ?
val b:List[Fruit]=List[Apple]() // Does compile.
}
产生编译错误:
type mismatch;
found : scala.collection.immutable.Set[sandbox.stackOverFlow.Apple]
required: Set[sandbox.stackOverFlow.Fruit]
Note: sandbox.stackOverFlow.Apple <: sandbox.stackOverFlow.Fruit, but trait Set is invariant in type A.
You may wish to investigate a wildcard type such as `_ <: sandbox.stackOverFlow.Fruit`. (SLS 3.2.10)
val a:Set[Fruit]=Set[Apple]()
^
编辑:
正如Jatin的回答所指出的,这个问题已在这里得到解答:Why is Scala's immutable Set not covariant in its type?
答案 0 :(得分:4)
Set
的类型参数(甚至是不可变的)是不变的(主要是因为Set[A]
继承自A => Boolean
,这是A
中的反对变体。 List
的类型参数是协变的。
至于如何解决这个问题,编译器为您提供了一个潜在的解决方案:使用通配符,例如
val a: Set[_ <: Fruit] = Set[Apple]()
答案 1 :(得分:2)
因为List的类型参数(声明为List[+A]
)是{-3}}(声明为Set[A]
)的共变量,所以它是不变的。
简而言之,
协方差是:将更广泛的类型转换为窄类型(例如将List[Animal
转换为List[Dog]
。
Contra-variance 正在将窄类型转换为更宽泛的类型。例如Function1[Dog, something]
扩展Function1[Animal, Something]
。在这里,您要将Dog
(缩小)转换为Animal
(更宽)
Invariance 不允许你做以上任何事情。
有几个链接可用于解释协方差和反方差:
答案 2 :(得分:1)
因为List
是协变的,所以ant Set
是不变的。看看定义:
sealed abstract class List[+A] extends...
trait Set[A] extends ...