So I have defined a Scala object using the following code:
trait SomeTrait {
def someMethod(): Unit
}
package somepackage1 {
object Impl1 extends SomeTrait {
def someMethod(): Unit = { }
}
object Impl2 extends SomeTrait {
def someMethod(): Unit = { }
}
}
I want to access the object given its fully qualified name i.e. somepackage1.Impl2
. A method something like following:
package object somewhereElse {
def getImpl(qualifiedName: String): SomeTrait = {
???
}
}
What should be the code as part of getImpl
method?
Here is a solution that uses the Java Reflection API (you might want to use the newer Scala Reflection API instead):
trait SomeTrait {
def someMethod(): Unit
}
package somepackage1 {
object Impl1 extends SomeTrait {
def someMethod(): Unit = { println("impl 1") }
}
object Impl2 extends SomeTrait {
def someMethod(): Unit = { println("impl 2") }
}
}
package object somewhereElse {
def getImpl(qualifiedName: String): SomeTrait = {
val clazz = Class.forName(qualifiedName + "$")
clazz
.getField("MODULE$")
.get(clazz)
.asInstanceOf[SomeTrait]
}
}
object Demo {
def main(args: Array[String]): Unit = {
somewhereElse.getImpl("somepackage1.Impl2").someMethod()
}
}
It's quite similar to Dima's comment above, with two minor differences: note the '$'
appended to class name, and also the .get(clazz)
instead of just .get()
(without the clazz
, it throws java.lang.NoSuchFieldException: MODULE$
).
When saved to file f.scala
, and compiled and invoked using
scalac f.scala && scala Demo
it prints:
impl 2