Scala不变的地图协方差

时间:2012-09-13 18:43:30

标签: scala covariance

我试图掌握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)

2 个答案:

答案 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,则需要确保ParserT是协变的,以便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}}