Scala val a:Set[Fruit]=Set[Apple]()不编译,为什么?怎么能修好呢?
行Scala val a:Set[Fruit]=Set[Apple]()不编译,为什么?怎么能修好呢?,scala,generics,Scala,Generics,行vala: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]() //
vala: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]()
^
类型不匹配;
找到:scala.collection.immutable.Set[sandbox.stackOverFlow.Apple]
必需:设置[沙箱.堆垛溢出.水果]
注意:sandbox.stackOverFlow.AppleSet
(甚至不可变)的类型参数是不变的(主要是因为Set[A]
继承自A=>Boolean
,这在A
中是反变的)。List
的类型参数是协变的
至于如何解决这个问题,编译器提供了一个潜在的解决方案:使用通配符,例如
val a: Set[_ <: Fruit] = Set[Apple]()
vala:Set[\up>,因为(声明为List[+a]
)的类型参数是共变的,而对于(声明为Set[a]
)它是不变的
总之,
协方差是:将较宽的类型转换为较窄的类型(例如将List[Animal
转换为List[Dog]
)。
相反,将狭义类型转换为广义类型。例如Function1[Dog,something]
扩展Function1[Animal,something]
。在这里,您将Dog
(狭义)转换为Animal
(广义)
不变性并不允许你做上述任何事情
有几个链接可以解释协方差和对方差:
(@serejja提到这是评论)
这是因为List
s是协变的,antSet
s是不变的
sealed abstract class List[+A] extends...
trait Set[A] extends ...
是的,但这有什么意义呢?@jhegedus请阅读此文,至于如何修复此问题,编译器提供了一个潜在的解决方案:使用通配符,例如val a:Set[\u Regis你能不能把这个作为一个答案,它解决了使用存在类型修复它的问题。我刚刚编辑了Jean-Philippe Pellet的答案,包括这个“修复”,我希望他不会介意