2010-06-14 3 views
30

dire, je donne les résultats suivants:Comment appeler une méthode Scala Object à l'aide de la réflexion?

trait SomeTrait { 
    def someMethod: String; 
} 

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

Je voudrais appeler « someMethod » en utilisant la réflexion que j'ai le nom de l'objet en tant que chaîne. Quelque chose comme:

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

ou quelque chose de similaire.

Merci

Répondre

13

Pour les classes, cela peut se faire assez facilement en utilisant la méthode standard de réflexion java classof. Pour les objets Scala, il est un peu plus de travail, mais il peut encore être fait:


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 
+2

Je pense qu'il fait briser l'attente des clients d'un objet compagnon (singleton) si vous créez de nouvelles instances de celui-ci. –

+0

Arjan - merci. C'est exactement ce que je cherchais. Thomas - C'est vrai. Mais vous pouvez toujours enrouler le code dans une fabrique d'objets et fournir le comportement singleton vous-même. – sanjib

19
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 
+0

C'est encore mieux. Merci Thomas. – sanjib

+2

Avez-vous besoin du manifeste? J'ai trouvé que 'Class.forName (nom +" $ "). GetField (" MODULE $ "). Get (null)' est suffisant. Ceci est autorisé pour les champs statiques. –

+1

Comment cela se traduit-il en 2.10 par réflexion? – bhericher

12

Depuis scala 2.10, nous pouvons utiliser la réflexion du 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 
Questions connexes