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

和自甴很熟 提交于 2019-12-05 19:26:05
Rex Kerr

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]]

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.

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