我试图掌握Scala中的协方差和逆变。我有这样的类 Message1和Message2是Message
的子类型sealed trait Parser[T <: Message]{
//... blah blah
}
class Parser1 extends Parser[Message1]{
}
class Parser2 extends Parser[Message2]{
}
现在我有一个模块(工厂),它将映射存储在一个不可变的Map
中var myMap = Map[String,Parser[Message]()
myMap += Map("Message1" -> new Parser1)
myMap += Map("Message2"-> new Parser2)
现在这不会编译。我错过了什么?
这是我得到的编译错误
[error] found : scala.collection.immutable.Map[java.lang.String,s.p.h.m.Parser1]
[error] required: (String, s.p.h.m.Parser[c.s.m.Message])
[error] myMap += Map("Message1" -> new Parser1)
答案 0 :(得分:2)
你得到的错误是什么?由于您的Parser
类层次结构,此处看起来您没有任何类型错误。
但是,看起来您正在尝试改变不可变映射,并且 会导致错误。此外,您应该将地图对添加到地图而不是新地图。试试这个:
val myMap = Map[String,Parser]()
val myMap1 = myMap + ("Message1" -> new Parser1)
val myMap2 = myMap1 + ("Message2" -> new Parser2)
如果您确实想要使用+=
而不是为每次更新创建新的val
,那么您可以使用scala.collection.mutable.Map
而不是默认(不可变)地图类型。
答案 1 :(得分:2)
您已经看到,您需要++=
将另一个地图的条目添加到地图中,而+
只需一个条目(密钥和值的元组)。如果您想保留var
,则需要确保Parser
中T
是协变的,以便Parser[Message1]
被视为Parser[Message]
的子类型(因为+
Map[String,Parser[Message]]
的结果将是现有条目和新条目的最近的超类型,然后在这种情况下将保留myMap
,因此它可以再次存储在trait Message; class Message1 extends Message; class Message2 extends Message
sealed trait Parser[+T <: Message] // !
class Parser1 extends Parser[Message1]
class Parser2 extends Parser[Message2]
var myMap = Map.empty[String,Parser[Message]]
myMap += "Message1" -> new Parser1
myMap += "Message2"-> new Parser2
myMap ++= Map( "Message1b"-> new Parser1, "Message2b"-> new Parser2 )
中:< / p>
{{1}}