The following describes how to create a new instance of type T at run time using Manifest :
trait MyTrait class MyClass1(val name: String) extends MyTrait class MyClass2(val name: String) extends MyTrait class Test[T <: MyTrait] { def createInstance[T](name: String)(implicit m: Manifest[T]): T = { m.runtimeClass.getConstructors()(0) .newInstance(name).asInstanceOf[T] } def doSomething() { val myClass = createInstance("joe") ... } } ... val test = new Test[MyClass1] test.doSomething
The createInstance method createInstance creates a new instance of one of the classes that implements MyTrait and calls the constructor with the given line. How to implement the same with TypeTag ?
Reimplemented with scala.reflect.runtime._
The following is the Test class, overridden as suggested by som-snytt:
class Test[T <: MyTrait] { import scala.reflect.runtime._ import scala.reflect.runtime.universe._ def createInstance[T: TypeTag](name: String): T = { val tt = typeTag[T] currentMirror.reflectClass(tt.tpe.typeSymbol.asClass).reflectConstructor( tt.tpe.members.filter(m => m.isMethod && m.asMethod.isConstructor ).iterator.next.asMethod )(name).asInstanceOf[T] } }
While I call createInstance on Test , it works:
val test = new Test[MyClass1] val myClass = test.createInstance("hello") // this works
But as soon as I define a new class derived from Test ...
class DerivedTest[T <: MyTrait] extends Test[T]
... and I call createInstance in this new class, like this ...
val test = new DerivedText[MyClass1] val myClass = test.createInstance("hello") // this crashes
... I get the following error:
java.util.NoSuchElementException: next on empty iterator at scala.collection.Iterator$$anon$2.next(Iterator.scala:39) at scala.collection.Iterator$$anon$2.next(Iterator.scala:37) at scala.collection.LinearSeqLike$$anon$1.next(LinearSeqLike.scala:62) at DerivedTest$class.createInstance(<console>:27) at $anon$1.createInstance(<console>:26) at .<init>(<console>:28) at .<clinit>(<console>) at .<init>(<console>:7) at .<clinit>(<console>) at $print(<console>) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) ...
Did I miss something?
reflection scala
j3d
source share