TypeTag
nie jest jeszcze zamiennikiem dla Manifest
, ponieważ jest częścią eksperymentalnej i niestabilnej refleksji Scala. Zdecydowanie nie powinno się go używać do produkcji od teraz.
Dla przypadku użycia pokazałeś, gdzie potrzebna jest tylko klasa wykonawcze (nie pełne informacje typu z rodzajowych itp), Scala 2.10 wprowadzonych ClassTag
, które można używać tak:
def newInstance[T: ClassTag] =
implicitly[ClassTag[T]].runtimeClass.newInstance.asInstanceOf[T]
czyli
def newInstance[T](implicit ct: ClassTag[T]) =
ct.runtimeClass.newInstance.asInstanceOf[T]
W każdym razie, Manifest
nie jest przestarzałe, więc myślę, że nadal można z niego korzystać.
EDIT:
Korzystanie TypeTag
aby osiągnąć ten sam:
import scala.reflect.runtime.universe._
def newInstance[T: TypeTag] = {
val clazz = typeTag[T].mirror.runtimeClass(typeOf[T])
clazz.newInstance.asInstanceOf[T]
}
Powyższe rozwiązanie nadal wykorzystuje pewne odbicie Java. Jeśli chcemy być purystyczne i używać tylko odbicie Scala, jest to rozwiązanie:
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]
}
Dzięki @ghik, ja nadal byłby zainteresowany dowiedzieć się, jak to zrobić z TypeTag, najlepiej przy zachowaniu pełnej informacji typu, czyli rodzaj wnioskowania powinna wnioskować 'newInstance [MojaKlasa {Int]]: MojaKlasa [Int] ' –
@DanielMahler Dodałem rozwiązanie oparte na 'TypeTag'. Zobacz moją edycję. – ghik
@ghik przy użyciu 'runtimeMirror (this.getClass.getClassLoader)' można uzyskać wyjątek, gdy 'T' nie jest załadowany z tego samego programu ładującego klasy co' this.type'. Powinieneś użyć lustra dołączonego do 'TypeTag':' typeTag [T] .mirror'. –