2012-09-13 127 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