我有scala的类型系统问题,我无法理解。下面的代码片段说明了这个问题。在类中可以拥有类型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())
}
}
答案 0 :(得分: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] = ....
或者,如果您输入多个条目,以便类型推断器选择基本类型:
val d = List((Concrete1(), 3.5), (Concrete2(), 4.5)).toMap
&#39; get&#39;但是,你使用总是会失败,因为你试图使用整个Map
作为索引:如果你提供了一个合理的密钥,它可以正常工作:
dv1.data.get(Concrete1())