Getting object instance by string name in scala
Solution 1
Scala is still missing a reflection API. You can get the an instance of the companion object by loading the companion object class:
import scala.reflect._
def companion[T](implicit man: Manifest[T]) : T =
man.erasure.getField("MODULE$").get(man.erasure).asInstanceOf[T]
scala> companion[List$].make(3, "s")
res0: List[Any] = List(s, s, s)
To get the untyped companion object you can use the class directly:
import scala.reflect.Manifest
def companionObj[T](implicit man: Manifest[T]) = {
val c = Class.forName(man.erasure.getName + "$")
c.getField("MODULE$").get(c)
}
scala> companionObj[List[Int]].asInstanceOf[List$].make(3, "s")
res0: List[Any] = List(s, s, s)
This depends on the way scala is mapped to java classes.
Solution 2
In scala 2.10 we can do like this
import scala.reflect.runtime.universe
val runtimeMirror = universe.runtimeMirror(getClass.getClassLoader)
val module = runtimeMirror.staticModule("package.ObjectName")
val obj = runtimeMirror.reflectModule(module)
println(obj.instance)
Solution 3
Adjustment to Thomas Jung's answer above: you would do better to say companion[List.type] because a) this should be a stable way to refer to it, not dependant on the name mangling scheme and b) you get the unerased types.
def singleton[T](implicit man: reflect.Manifest[T]) = {
val name = man.erasure.getName()
assert(name endsWith "$", "Not an object: " + name)
val clazz = java.lang.Class.forName(name)
clazz.getField("MODULE$").get(clazz).asInstanceOf[T]
}
scala> singleton[List.type].make(3, "a")
res0: List[java.lang.String] = List(a, a, a)
Solution 4
Barring reflection tricks, you can't. Note, for instance, how the method companion
is defined on Scala 2.8 collections -- it is there so an instance of a class can get the companion object, which is otherwise not possible.
Dave
Updated on July 12, 2022Comments
-
Dave almost 2 years
I need the object (or "singleton object" or "companion object"... anything but the class) defined by a string name. In other words, if I have:
package myPackage object myObject
...then is there anything like this:
GetSingletonObjectByName("myPackage.myObject") match { case instance: myPackage.myObject => "instance is what I wanted" }
-
Thomas Jung over 14 yearsCould you add a link to the source, please?
-
Daniel C. Sobral over 14 yearslampsvn.epfl.ch/trac/scala/browser/scala/trunk/src/library/…, though, hopefully, 2.8's Scaladoc 2 will soon contain links to the source, as already happens with 2.7.
-
Dave over 14 yearsHoly cow. Do you know if this syntax is a fixed part of the Scala spec (as fixed as anything else in the language, anyway)? It seems like a bad idea to rely on this. And since my goal was to make the code clearer... Thank you!
-
IttayD over 13 yearsHow is this better than just
List.make(3, "a")
? The OP wanted to get the object by string name -
pdinklag about 13 yearsAs he mentioned, there is no reflection API in Scala yet, so whether this is covered by the Scala spec or not, this is the only way for you to do it. I noticed this question / answer is over a year old, are there any news here?
-
appbootup almost 13 yearsThanks! This is exactly what I was looking for. It's certainly a hack, but less dirty than what I managed to come up with.