TypeTag
ist noch kein Ersatz für Manifest
, weil es ein Teil der experimentellen und instabilen Scala-Reflexion ist. Sie sollten es auf keinen Fall für die Produktion verwenden.
Für den Anwendungsfall Sie zeigte, wo nur Laufzeitklasse (nicht vollständige Typinformationen mit Generika etc.), Scala 2.10 eingeführt ClassTag
benötigt, die Sie so verwenden können:
def newInstance[T: ClassTag] =
implicitly[ClassTag[T]].runtimeClass.newInstance.asInstanceOf[T]
oder:
def newInstance[T](implicit ct: ClassTag[T]) =
ct.runtimeClass.newInstance.asInstanceOf[T]
Wie auch immer, Manifest
ist noch nicht veraltet, also denke ich, dass Sie es immer noch verwenden können.
EDIT:
TypeTag
Unter Verwendung derselben zu erreichen:
import scala.reflect.runtime.universe._
def newInstance[T: TypeTag] = {
val clazz = typeTag[T].mirror.runtimeClass(typeOf[T])
clazz.newInstance.asInstanceOf[T]
}
Die obige Lösung verwendet immer noch einige Java Reflexion. Wenn wir puristisch sein wollen und nur Scala Reflexion verwenden, ist dies die Lösung:
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]
}
Dank @ghik, habe ich noch herausfinden, wäre daran interessiert, wie es zu tun mit TypeTag, vorzugsweise während vollständige Typinformationen zu bewahren, sollte also Typinferenz schließen 'newInstance [MyClass {Int]]: MyClass [Int] ' –
@DanielMahler Ich habe 'TypeTag'-basierte Lösung hinzugefügt. Bitte sehen Sie meine Bearbeitung. – ghik
@ghik Wenn Sie 'runtimeMirror (this.getClass.getClassLoader) 'verwenden, können Sie eine Ausnahme erhalten, wenn' T' nicht mit dem gleichen Klassenlader wie 'this.type' geladen ist. Sie sollten einen Mirror verwenden, der an 'TypeTag' angehängt ist:' typeTag [T] .mirror'. –