Ideal to handle scala constructors in a dynamic instance

I compiled this working code that dynamically creates an instance of the class from the given name: String (see below). This works for simple case classes and case classes that have one constructor.

I'm not sure how to handle the general case when there are multiple constructors. I suppose that they can be distinguished only by their signatures, but finding a conceptual interaction between related objects, classes and classes of events is a bit confusing. What will be the full description of all the scenarios of "construction" that need to be taken into account, or, how would you develop this to become completely general?

Demonstrating its inflexibility, this code awkwardly fails when viewing a companion object.

Hopefully this code will give a convenient test and stream to fiddle if someone needs to join this thought.

 import scala.reflect.runtime.universe case class CaseClass(foo: Int) { println(s"${getClass.getSimpleName} Instantiated with $foo") } class BaseClass(foo: Int) { println(s"${getClass.getSimpleName} Instantiated with $foo") } object BaseClass { def apply(foo:Int) = { println(s"going through companion object ${getClass.getSimpleName}") new BaseClass(foo+10) } } class GenericClass[T](foo: T) { println(s"${getClass.getSimpleName} Instantiated with $foo") } object Inst { private def log(s: String) = println(Console.YELLOW + Console.BOLD + s + Console.RESET) private def selectConstructor(symbol: universe.Symbol) = { val constructors = symbol.typeSignature.members.filter(_.isConstructor).toList if (constructors.length > 1) log( s"""Warning: $symbol has several constructors, arbitrarily picking the first one: | ${constructors.mkString("\n ")}""".stripMargin) constructors.head.asMethod } def apply(className: String, arg: Any) = { val runtimeMirror: universe.Mirror = universe.runtimeMirror(getClass.getClassLoader) val classSymbol: universe.ClassSymbol = runtimeMirror.classSymbol(Class.forName(className)) val classMirror: universe.ClassMirror = runtimeMirror.reflectClass(classSymbol) if (classSymbol.companion.toString() == "<none>") // TODO: use nicer method "hiding" in the api? { log(s"Info: $className has no companion object") val constructorMirror = classMirror.reflectConstructor(selectConstructor(classSymbol)) // we can reuse it constructorMirror(arg) } else { val companionSymbol = classSymbol.companion log(s"Info: $className has companion object $companionSymbol") val constructorMirror = classMirror.reflectConstructor(selectConstructor(classSymbol)) // we can reuse it constructorMirror(arg) } } } object Test extends App { val c1 = Inst("BaseClass", 3) val c2 = Inst("BaseClass", 4) val cc = Inst("CaseClass", 5) val gc1 = Inst("GenericClass", "I am generic") val gc2 = Inst("GenericClass", gc1) println(s"""\nthese objects have been instantiated:\n${List(c1,c2,cc,gc1,gc2).mkString("\n")}""") } 

Note that this requires build.sbt or similar:

 lazy val reflection = (project in file(".")) .settings( scalaVersion := "2.11.7", libraryDependencies ++= Seq( "org.scala-lang" % "scala-compiler" % scalaVersion.value % "provided", "org.scala-lang" % "scala-library" % scalaVersion.value % "provided" ) ) 
+2
scala
Dec 11 '15 at 16:18
source share

No one has answered this question yet.

See similar questions:

43
Scala: How to dynamically instantiate an object and call a method using reflection?

or similar:

790
Is the Scala 2.8 collection library "the longest suicide record in history"?
676
Scala vs Groovy vs Clojure
595
The difference between an object and a class in Scala
492
What are the benefits of underscoring in Scala?
19
How to create a TestActorRef in Scala for an actor with constructor parameters?
5
Scala abstract method is null in a superclass when a subclass implements it with val?
5
a scala deleted member exception
four
Scala ambiguity with seamless function calls
3
How to build dynamic sequence in scala macro?
0
Scala: static val or def for case class



All Articles