2013-07-01 56 views
1

我有一個類似的系統問題,我不明白的斯卡拉。下面的代碼片段說明了這個問題。在類中可以具有類型A或A的子類型的鍵的地圖成員的正確方法是什麼? 我認爲第二種方法是正確的,但當我嘗試從地圖中獲取元素時會出錯。這與存在類型有關嗎?斯卡拉類型錯誤類地圖成員鍵入與存在類型

sealed abstract class MyBaseType 
case class Concrete1() extends MyBaseType 
case class Concrete2() extends MyBaseType 

case class DictVariant1(data: Map[MyBaseType, Double]) 
case class DictVariant2(data: Map[_ <: MyBaseType, Double]) 

object App { 
    def main(args: Array[String]) { 
    val d = List((Concrete1(), 3.5)).toMap 

    /* this fails with: 
    * type mismatch; 
    * found: scala.collection.immutable.Map[Concrete1,Double] 
    * required: Map[MyBaseType,Double] 
    * Note: Concrete1 <: MyBaseType, but trait Map is invariant in type A. 
    * You may wish to investigate a wildcard type such as `_ <: MyBaseType`. 
    * (SLS 3.2.10) 
    * 
    */ 
    val dv1 = DictVariant1(d) 
    dv1.data.get(d) 

    /* Works fine */ 
    val dv2 = DictVariant2(d) 

    /* this fails with: 
    * type mismatch; 
    * found: d.type (with underlying type scala.collection.immutable.Map[Concrete1,Double]) 
    * required: _$1  
    * 
    */ 
    dv2.data.get(Concrete1()) 
    } 
} 

回答

1

除非你明確要求得到鑰匙退了出來作爲靜態正確的亞型(這似乎不太可能),那麼下面的工作:

case class DictVariant1(data: Map[MyBaseType, Double]) 
val d = List((Concrete1() : MyBaseType, 3.5)).toMap 
val dv1 = DictVariant1(d) 

使用類型歸屬力量Concrete1()被視爲基本類型的一個實例;你會得到同樣的效果,如果你增加了一個明確的類型d

val d : Map[MyBaseType, Double] = .... 

或者,如果你把這樣的多個項目,inferencer採基本類型類型:

val d = List((Concrete1(), 3.5), (Concrete2(), 4.5)).toMap 

「獲取「你用的是總是但是失敗,因爲你想使用整個Map作爲索引:

dv1.data.get(Concrete1()) 
+0

非常感謝你:如果你提供一個合理的關鍵,它工作正常。由於get是一個錯誤,我會編輯我的源代碼。當然,這是我以後的關鍵,而不是地圖本身。 – Rickard