2010-06-14 16 views
30

decir, Tengo el siguiente:¿Cómo llamo a un método de Objeto Scala utilizando la reflexión?

trait SomeTrait { 
    def someMethod: String; 
} 

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

me gustaría llamar "algunMetodo" por medio de la reflexión como tengo el nombre del objeto como una cadena. Algo así como:

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

o algo similar.

Gracias

Respuesta

13

Para las clases, esto se puede hacer muy fácilmente usando el método classof java reflexión estándar. Para los objetos Scala, que es un poco más de trabajo, pero todavía se puede hacer:


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

creo que lo hace rompa la expectativa de los clientes de un objeto acompañante (singleton) si crea nuevas instancias de este. –

+0

Arjan - gracias. Eso es exactamente lo que estaba buscando. Thomas - Eso es cierto. Pero siempre puede envolver el código en una fábrica de objetos y proporcionar el comportamiento de singleton usted mismo. – 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

Esto es aún mejor. Gracias Thomas. – sanjib

+2

¿Necesita el manifiesto? Descubrí que 'Class.forName (name +" $ "). GetField (" MODULE $ "). Get (null)' es suficiente. Esto está permitido para campos estáticos. –

+1

¿Cómo se traduce en 2.10 con reflexión? – bhericher

12

Desde Scala 2.10, podemos utilizar el reflejo del Módulo:

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 
Cuestiones relacionadas