scala – 从类[A]中获取TypeTag [A]
发布时间:2020-12-16 09:56:40 所属栏目:安全 来源:网络整理
导读:我有createOld方法,我需要覆盖,我不能改变它.我想使用TypeTag在createNew中模式匹配提供的类型.目标是找出如何从createOld调用createNew.我目前的理解是编译器在createOld方法中没有足够的关于A的类型信息,如果它还没有TypeTag [A]. object TypeTagFromClass
我有createOld方法,我需要覆盖,我不能改变它.我想使用TypeTag在createNew中模式匹配提供的类型.目标是找出如何从createOld调用createNew.我目前的理解是编译器在createOld方法中没有足够的关于A的类型信息,如果它还没有TypeTag [A].
object TypeTagFromClass { class C1 class C2 // How to get TypeTag[A] needed by createNew? def createOld[A](c: Class[A]): A = createNew ??? def createNew[A : TypeTag]: A = { val result = typeOf[A] match { case a if a =:= typeOf[C1] => new C1() case a if a =:= typeOf[C2] => new C2() } result.asInstanceOf[A] } } 解决方法
可以使用Scala反射从类创建TypeTag,但我不确定TypeCreator的这种实现是否绝对正确:
import scala.reflect.runtime.universe._ def createOld[A](c: Class[A]): A = createNew { val mirror = runtimeMirror(c.getClassLoader) // obtain runtime mirror val sym = mirror.staticClass(c.getName) // obtain class symbol for `c` val tpe = sym.selfType // obtain type object for `c` // create a type tag which contains above type object TypeTag(mirror,new TypeCreator { def apply[U <: Universe with Singleton](m: api.Mirror[U]) = if (m eq mirror) tpe.asInstanceOf[U # Type] else throw new IllegalArgumentException(s"Type tag defined in $mirror cannot be migrated to other mirrors.") }) } 但是,如果您不需要检查通用参数和完整的Scala类型信息,则不需要完整的TypeTag.你可以使用ClassTags: def createNew[A: ClassTag]: A = { val result = classTag[A].runtimeClass match { case a if a.isAssignableFrom(classOf[C1]) => new C1() case a if a.isAssignableFrom(classOf[C2]) => new C2() } result.asInstanceOf[A] } 或者用一些隐含的糖: implicit class ClassTagOps[T](val classTag: ClassTag[T]) extends AnyVal { def <<:(other: ClassTag[_]) = classTag.runtimeClass.isAssignableFrom(other.runtimeClass) } def createNew[A: ClassTag]: A = { val result = classTag[A] match { case a if a <<: classTag[C1] => new C1() case a if a <<: classTag[C2] => new C2() } result.asInstanceOf[A] } 您可以使用普通的旧Java newInstance()方法进一步简化: def createNew[A: ClassTag]: A = classTag[A].runtimeClass.newInstance().asInstanceOf[A] 当然,这只有在您不需要不同类的不同构造函数参数时才有效. 从createOld调用这个createNew比使用TypeTags的那个简单得多: def createOld[A](c: Class[A]): A = createNew(ClassTag[A](c)) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |