views:

110

answers:

2

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

+8  A: 

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
Arjan Blokzijl
I think it does break the expectation of clients of a companion (singleton) object if you create new instances of it.
Thomas Jung
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
+2  A: 
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
Thomas Jung
This is even better. Thanks Thomas.
sanjib