In Scala, how to test the type of an 'Any' object against a type with type parameter?

大憨熊 提交于 2019-12-07 12:18:24

问题


I am trying to get a type-safe way of converting the result of parsing a JSON string. I want to check whether a field is Map[String, any] or a plain string. My first attempt is

def test(x:Any) = {
    x match {
        case m:Map[String,Any] => ...
        ...
}

This causes "non-variable type argument String in type pattern Map[String,Any] is unchecked since it is eliminated by erasure"

Looking through the document of TypeTag and ClassTag, I could not find a good way to accomplish that. The following code does not cause the warning, but I wonder why it works.

type StringMap = Map[String,Any]
def test(x:Any) = {
    x match {
        case m:StringMap => ...
        ...
}

回答1:


It was a bug. It's fixed in 2.11:

scala> type StringMap = Map[String, Any]
defined type alias StringMap

scala> (Map(4 -> true): Any) match {
     |   case m: StringMap => true
     |   case _ => false
     | }
<console>:10: warning: non-variable type argument String in type pattern scala.collection.immutable.Map[String,Any] (the underlying of StringMap) is unchecked since it is eliminated by erasure
                case m: StringMap => true
                        ^
res0: Boolean = true

The reason it doesn't work is that you can't tell, due to erasure, what the type arguments were. If you want to be sure it's a Map[String, Any] instead of some other kind of map, you have to go check every key and make sure it's a String.

case m: Map[_,_] if m.keySet.forall(_.isInstanceOf[String]) => 
  m.asInstanceOf[Map[String,Any]]



回答2:


It's impossible to check the type parameters, but

I want to check whether a field is Map[String, any] or a plain string

is easy:

x match {
  case s: String => ...
  // you can add cases for numbers, etc. here
  case m: Map[_, _] => ... m.asInstanceOf[Map[String, Any]]
}

Looking through the document of TypeTag and ClassTag, I could not find a good way to accomplish that.

Tags are created by the compiler using static type information, so in your case you'll only have class or type tag of Any.



来源:https://stackoverflow.com/questions/23155288/in-scala-how-to-test-the-type-of-an-any-object-against-a-type-with-type-param

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!