匹配类型在地图上失败

时间:2016-01-27 11:04:34

标签: scala

我正在学习Scala并尝试编写一些简单的代码。

当我尝试编写这样的方法时:

def func(value: Any) {
  value match {
    case i: Int => println(1)
    case vector: Vector[Any] => println(2)
    case map: Map[Any, Any] => println(3)
    case _ => println(4)
  }
}

我收到了警告:

[warn]........:31: non-variable type argument Any in type pattern scala.collection.immutable.Map[Any,Any] (the underlying of Map[Any,Any]) is unchecked since it is eliminated by erasure
[warn]       case map: Map[Any, Any] => println(3)
[warn]                    ^
[warn] one warning found

我想知道为什么使用Map[Any, Any]会收到警告但Vector[Any]不会。

2 个答案:

答案 0 :(得分:4)

原因是Map在其第一个类型参数中是不变的。这意味着并非任何地图都是Map[Any,Any]的子类型。 相反,Vector在其类型参数中是协变的,因此任何Vector始终是Vector[Any]的子类型,这意味着编译器不需要检查实际的运行时类型为Vector[Any](由于删除无法做到),即使它是Vector[String],也可以将其作为Vector[Any]进行处理。

答案 1 :(得分:3)

问题是Map[X, Y]在其类型参数X中不是协变的(但是Vector[X]是)。

这是什么意思?假设B <: A(读,BA的子类型。)

然后我们有Vector[B] <: Vector[A]。这是有道理的:如果我们从x检索元素Vector[B],它将是B。这意味着它也是子类型关系的A。 (类似的论点适用于所有其他方法。)

遵循类似的推理,Map[X, B] <: Map[X, A]用于所有X(元素检索是按键而不是索引,但要点保持不变)。

但是,这不适用于Map的第一个类型参数。对某些Map[B, X] <: Map[A, X]假设X

我们现在可以执行以下操作:

val x: Map[B, X] = ???
x.get(b: B) // makes sense

val y: Map[A, X] = x // must be ok, Map[B, X] <: Map[A, X]
y.get(a: A) // bad! x doesn't know how to "get" with something of type `A`

因此,Map[_, _]不一定是Map[Any, Any]。要修复错误消息,请使用:

case map: Map[_, _] => ...