使用TypeTag和ClassTag在Scala中进行多态实例化
发布时间:2020-12-16 18:42:51 所属栏目:安全 来源:网络整理
导读:在 Scala 2.9中,可以实现多态实例化 def newInstance[T](implicit m: Manifest[T]) = m.erasure.newInstance.asInstanceOf[T] 但截至2.10 Manifest正在被TypeTag取代, 并且我不清楚如何使用TypeTag实现类似的功能. 如果TypeTag版本保留了所有可用的类型信息,
在
Scala 2.9中,可以实现多态实例化
def newInstance[T](implicit m: Manifest[T]) = m.erasure.newInstance.asInstanceOf[T] 但截至2.10 Manifest正在被TypeTag取代, 我知道上面只适用于不需要构造函数args的traits / classes, 解决方法
TypeTag还不是Manifest的替代品,因为它是实验性和不稳定Scala反射的一部分.你现在肯定不应该把它用于生产.
对于你展示的用例,只需要运行时类(不是带有泛型等的完整类型信息),Scala 2.10引入了ClassTag,你可以这样使用: def newInstance[T: ClassTag] = implicitly[ClassTag[T]].runtimeClass.newInstance.asInstanceOf[T] 要么: def newInstance[T](implicit ct: ClassTag[T]) = ct.runtimeClass.newInstance.asInstanceOf[T] 无论如何,Manifest还没有被弃用,所以我猜你仍然可以使用它. 编辑: 使用TypeTag实现相同: import scala.reflect.runtime.universe._ def newInstance[T: TypeTag] = { val clazz = typeTag[T].mirror.runtimeClass(typeOf[T]) clazz.newInstance.asInstanceOf[T] } 上面的解决方案仍然使用一些Java反射.如果我们想要纯粹并且只使用Scala反射,那么这就是解决方案: def newInstance[T: TypeTag]: T = { val tpe = typeOf[T] def fail = throw new IllegalArgumentException(s"Cannot instantiate $tpe") val noArgConstructor = tpe.member(nme.CONSTRUCTOR) match { case symbol: TermSymbol => symbol.alternatives.collectFirst { case constr: MethodSymbol if constr.paramss == Nil || constr.paramss == List(Nil) => constr } getOrElse fail case NoSymbol => fail } val classMirror = typeTag[T].mirror.reflectClass(tpe.typeSymbol.asClass) classMirror.reflectConstructor(noArgConstructor).apply().asInstanceOf[T] } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
推荐文章
站长推荐
热点阅读