How to cast a variable to certain runtime type got from TypeCast in Scala

陌路散爱 提交于 2019-11-29 14:32:07

问题


The asInstanceOf[T] works for "simple" case where the type T is given explicitly by code: e.g.

scala> val x: Any = 5
x: Any = 5

scala> x.asInstanceOf[Int]
res50: Int = 5

scala> val m1: Any = Map[String, Int]("a"->1, "b"->2)
m1: Any = Map(a -> 1, b -> 2)

scala> m.asInstanceOf[Map[String, Int]]
res51: Map[String,Int] = Map(a -> 1, 2 -> b)

scala> val m2: Any = Map[Any,Any]("a"->1, 2->"b")
m2: Any = Map(a -> 1, 2 -> b)

scala> m.asInstanceOf[Map[Any, Any]]
res52: Map[Any,Any] = Map(a -> 1, 2 -> b)

But when the type T is retrieved at runtime through TypeTags, asInstanceOf[T] does not work. For example:

scala> val intT = typeTag[Int].tpe
intT: reflect.runtime.universe.Type = Int

scala> x.asInstanceOf[intT]
<console>:12: error: not found: type intT
              x.asInstanceOf[intT]

The error says it clear that intT is not a type. So reflect.runtime.universe.Type is not a real type? How to cast a value to certain type using typeTag information?


回答1:


intT isn't a type, but an instance of Type. Confusing, for sure. I'm not sure if there is something built into the reflection API that does this, but you can easily write a method that will cast to A given an element Any and a TypeTag[A].

def cast[A](a: Any, tt: TypeTag[A]): A = a.asInstanceOf[A]

scala> val intT = typeTag[Int]
intT: reflect.runtime.universe.TypeTag[Int] = TypeTag[Int]

scala> val a: Any = 1
a: Any = 1

scala> cast(a, intT)
res101: Int = 1

Another variant using an implicit class:

implicit class TypeTagCast(a: Any) {
    def fromTypeTag[A](tt: TypeTag[A]): A = a.asInstanceOf[A]
 }

scala> a.fromTypeTag(intT)
res106: Int = 1


来源:https://stackoverflow.com/questions/29399090/how-to-cast-a-variable-to-certain-runtime-type-got-from-typecast-in-scala

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