我正在学习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]
不会。
答案 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
(读,B
是A
的子类型。)
然后我们有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[_, _] => ...