2012-09-13 67 views
0

我试图掌握Scala中的协变和逆变。我有一组类这样消息1和消息2的消息亚型Scala不可变映射协变

sealed trait Parser[T <: Message]{ 
    //... blah blah 
} 

class Parser1 extends Parser[Message1]{ 
} 

class Parser2 extends Parser[Message2]{ 
} 

现在我有anothe模块(工厂),存储映射在一个不变的地图

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

请提供工作代码。 Message1是Message的一个子类型吗? 'var myMap = Map [String,Parser]()'不是有效的代码,因为'Parser'接受一个类型参数。 –

+0

对不起,我错过了它,当我将所有专有名称替换为通用名称.. – questionersam

回答

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) 
2

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

但是,它看起来像你试图改变一个不可变的地图,并且会导致一个错误。此外,您应该在地图上添加地图对,而不是新地图。试试这个:

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

如果你真的想用+=,而不是创建每次更新新val那么你可以使用scala.collection.mutable.Map而不是默认的(immutable)的地图类型。

+0

编辑与编译错误我得到 – questionersam

+0

编辑:修复了错字,并添加了编译错误我得到 – questionersam

+0

@DaoWen ..啊现在。我认为'+'与另一张地图一起工作.. – questionersam