[英]Cast a variable to runtime type from existential typed TypeCast in Scala
This thread addressed how to use TypeTag
to get runtime type of type parameters when used with Existential
type. 该线程解决了在与
Existential
类型一起使用时如何使用TypeTag
获取类型参数的运行时类型。 Another thread addressed how to cast a variable to its runtime type retrieved from TypeTag
. 另一个线程解决了如何将变量转换为从
TypeTag
检索到的运行时类型。
My question builds on the aforementioned threads (kind of a combination of the two scenarios).我的问题基于上述线程(两种情况的结合)。 Parts of the code is duplicated from the two threads for clarity.
为清楚起见,部分代码是从两个线程中复制的。
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> def cast[A](a: Any, tt: TypeTag[A]): A = a.asInstanceOf[A]
cast: [A](a: Any, tt: reflect.runtime.universe.TypeTag[A])A
scala> abstract class Animal[T](implicit tt: TypeTag[T]) {
| val ttag = tt
| }
defined class Animal
scala> case object Dog extends Animal[Int]
defined object Dog
scala> case object Cat extends Animal[String]
defined object Cat
scala> val aa: List[(Animal[_], Any)] = List((Dog, 5), (Cat, "stringgg"), (Dog, 2))
aa: List[(Animal[_], Any)] = List((Dog,5), (Cat,stringgg), (Dog,2))
scala> aa(0)._1.ttag
res25: reflect.runtime.universe.TypeTag[_] = TypeTag[Int]
scala> aa(1)._1.ttag
res26: reflect.runtime.universe.TypeTag[_] = TypeTag[String]
scala> cast(aa(0)._2, aa(0)._1.ttag)
res27: Any = 5
scala> cast(aa(1)._2, aa(1)._1.ttag)
res28: Any = stringgg
In short, the last two lines: cast(value, TypeTag[_])
always return a value of type Any
.简而言之,最后两行:
cast(value, TypeTag[_])
总是返回Any
类型的值。 But my intention is to cast these values to the correct type stored in Dog|Cat.ttag
, which, unfortunately, is not TypeTag[Int]
or TypeTag[String]
but TypeTag[_]
due to usage of existential
type.但我的意图是将这些值转换为存储在
Dog|Cat.ttag
中的正确类型,不幸的是,由于existential
类型的使用,它不是TypeTag[Int]
或TypeTag[String]
而是TypeTag[_]
。 Is there any solution for it?有什么解决办法吗?
Edit 1:编辑 1:
Despite the field ttag
is of type TypeTag[_]
, ttag.tpe
does have the right "type" (but as an instance of reflect.runtime.universe.Type
).尽管字段
ttag
的类型为TypeTag[_]
, ttag.tpe
确实具有正确的“类型”(但作为reflect.runtime.universe.Type
的实例)。 Is it possible to use the typetag.tpe
to cast to the right type?是否可以使用
typetag.tpe
转换为正确的类型?
你可以改变cast方法, def cast[A](a: Any, tt: TypeTag[_]): A = a.asInstanceOf[A]
和
val x: Int = cast(aa(0)._2, aa(0)._1.ttag)
pair with path dependent type, you can type cast as following code shows:与路径依赖类型配对,您可以按以下代码显示类型转换:
import languageFeature.existentials
object TestExistential {
def main(args: Array[String]): Unit = {
val aa: Array[(Animal[T], T) forSome {type T}] = Array((Dog, 5:Integer), (Cat, "stringgg"), (Dog, 2:Integer))
aa.foreach(p=>{
val ani = p._1
val attr = p._2 // compiler weakness: existential type T is not unify with ani.castType
assert(ani.attrTyp.isAssignableFrom(attr.getClass))// because of boxing, real type is Integer not Int
assert(ani.clzTyp.isAssignableFrom(ani.getClass))
val typedAni:ani.castType = ani.asInstanceOf[ani.castType]
println(s"$typedAni of type Animal[${ani.attrTyp}] with $attr")
})
}
abstract class Animal[T]{
type castType = Animal[T]
val attrTyp: Class[T]
val clzTyp: Class[castType]
}
case object Dog extends Animal[Integer] {
override val attrTyp: Class[Integer] = classOf[Integer]
override val clzTyp: Class[Dog.castType] = classOf[Dog.castType]
}
case object Cat extends Animal[String] {
override val attrTyp: Class[String] = classOf[String]
override val clzTyp: Class[Cat.castType] = classOf[Cat.castType]
}
}
if typing in scala repl, you can see the reply:如果输入scala repl,可以看到回复:
scala> val typedAni:ani.castType = ani.asInstanceOf[ani.castType]
typedAni: ani.castType = Dog
scala> typedAni
res0: ani.castType = Dog
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.