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