How do I call a Scala Object method using reflection?

19,870

Solution 1

def companion[T](name : String)(implicit man: Manifest[T]) : T = 
    Class.forName(name + "$").getField("MODULE$").get(man.erasure).asInstanceOf[T]

val result = companion[SomeTrait]("SomeObject").someMethod

Solution 2

Since scala 2.10, we can use the reflection of Module:

import scala.reflect.runtime.universe

val runtimeMirror = universe.runtimeMirror(getClass.getClassLoader)
val module = runtimeMirror.staticModule("SomeObject")
val obj = runtimeMirror.reflectModule(module)
val someTrait:SomeTrait = obj.instance.asInstanceOf[SomeTrait]  
someTrait.someMethod

Solution 3

For classes, this can be done pretty easily using the standard java reflection classOf method. For Scala objects, it is a bit more work, but it still can be done:


trait SomeTrait { def someMethod: String}
object SomeObject extends SomeTrait { def someMethod = "something"}

class SomeClass extends SomeTrait { def someMethod = "something"}

object Main {
 def main(args:Array[String]) = {
    val someClassTrait:SomeTrait = Class.forName("SomeClass").newInstance().asInstanceOf[SomeTrait]
    println("calling someClassTrait: " + someClassTrait.someMethod)
    val objectName = "SomeObject$"
    val cons = Class.forName(objectName).getDeclaredConstructors(); 
    cons(0).setAccessible(true);
    val someObjectTrait:SomeTrait = cons(0).newInstance().asInstanceOf[SomeTrait]
    println("calling someObjectTrait: " + someObjectTrait.someMethod)
  }
}

//prints:
calling someClassTrait: something
calling someObjectTrait: something
Share:
19,870
sanjib
Author by

sanjib

Updated on June 07, 2022

Comments

  • sanjib
    sanjib almost 2 years

    say, I have the following:

    trait SomeTrait {
      def someMethod: String;
    }
    
    object SomeObject extends SomeTrait {
      def someMethod = "something";
    }
    

    I would like to call "someMethod" using reflection as I have the object name as a String. Something like:

    val objectName = "SomeObject"  
    val someTrait:SomeTrait = ???.asInstanceOf[SomeTrait]  
    someTrait.someMethod
    

    or something similar.

    Thanks

  • Thomas Jung
    Thomas Jung almost 14 years
    I think it does break the expectation of clients of a companion (singleton) object if you create new instances of it.
  • sanjib
    sanjib almost 14 years
    Arjan - thanks. That's exactly what I was looking for. Thomas - That's true. But you could always wrap the code in an object factory and provide the singleton behavior yourself.
  • sanjib
    sanjib almost 14 years
    This is even better. Thanks Thomas.
  • 0__
    0__ almost 11 years
    Do you need the manifest? I found that Class.forName(name + "$").getField("MODULE$").get(null) is sufficient. This is allowed for static fields.
  • bhericher
    bhericher almost 11 years
    How does it translate in 2.10 with reflection?
  • Kevin Meredith
    Kevin Meredith about 10 years
    Using Scala 2.10.2, my code threw an exception on Class.forName(name + "$").getField("MODULE$")
  • BdEngineer
    BdEngineer over 5 years
    @Thomas Jung , what is the "$" here , what it refer too , sorry me new to scala.