0

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

2 回答 2

2

你得到的错误是什么?Parser由于您的类层次结构,您在这里看起来不会有任何类型错误。

但是,您似乎正在尝试更改不可变映射,这导致错误。此外,您应该将地图对添加到地图而不是新地图。试试这个:

val myMap = Map[String,Parser]()
val myMap1 = myMap + ("Message1" -> new Parser1)
val myMap2 = myMap1 + ("Message2" -> new Parser2)

如果您真的想使用而不是为每个更新+=创建一个新的,那么您可以使用而不是默认(不可变)映射类型。valscala.collection.mutable.Map

于 2012-09-13T18:47:32.403 回答
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 )
于 2012-09-14T06:19:55.643 回答