scala - Scala 中使用 TypeTag 和 ClassTag 的多态实例化

标签 scala reflection scala-2.10

在 Scala 2.9 中,可以将多态实例化实现为

def newInstance[T](implicit m: Manifest[T]) =
    m.erasure.newInstance.asInstanceOf[T]

但截至 2.10 Manifest正在替换为 TypeTag ,
我不清楚如何使用 TypeTag 实现类似的功能.
我希望 TypeTag 版本保留所有可用的类型信息。

我知道以上仅适用于不需要构造函数参数的特征/类,
然后它并不总是有效,但它足以满足我的需要。
如果我能做得更好,新的反射 API 就太好了。

最佳答案

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

关于scala - Scala 中使用 TypeTag 和 ClassTag 的多态实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18499384/

相关文章:

delphi - Delphi中如何使用SuperObject调用使用Object作为参数的方法?

scala - 使用特征中的抽象类型解决类型删除问题

scala - 编译器错误? java.lang.ClassCastException : scala. collection.mutable.WrappedArray$ofRef 无法转换为 java.lang.Integer

scala - Gatling:当上一个请求没有 JSON 响应时,如何在下一个请求中传递值?

Scala 从列表中生成唯一的对

scala - 逆变的例子

斯卡拉 : generics and variable inheritance issue

scala - 非时间戳列上的 Spark 结构化流窗口

c++ - 使用 Boost Hana 反射(reflect) C 风格数组

java - 使用java反射通过其setter方法设置字段