reflection - Polymorphic instantiation in Scala using TypeTag and ClassTag -
in scala 2.9 1 implement polymorphic instantiation as
def newinstance[t](implicit m: manifest[t]) = m.erasure.newinstance.asinstanceof[t]
but of 2.10 manifest
being replaced typetag
, , not clear me how achieve similar typetag
. prefer if typetag version preserved available type information.
i know above works traits/classes not require constructor args, , ven not work, works enough need. if can better new reflection apis great.
typetag
not yet replacement manifest
because it's part of experimental , unstable scala reflection. shouldn't use production of now.
for use case showed, runtime class needed (not full type information generics etc.), scala 2.10 introduced classtag
, can use this:
def newinstance[t: classtag] = implicitly[classtag[t]].runtimeclass.newinstance.asinstanceof[t]
or:
def newinstance[t](implicit ct: classtag[t]) = ct.runtimeclass.newinstance.asinstanceof[t]
anyway, manifest
isn't deprecated yet, guess can still use it.
edit:
using typetag
achieve same:
import scala.reflect.runtime.universe._ def newinstance[t: typetag] = { val clazz = typetag[t].mirror.runtimeclass(typeof[t]) clazz.newinstance.asinstanceof[t] }
the above solution still uses java reflection. if want puristic , use scala reflection, solution:
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] }
Comments
Post a Comment