2009-12-16 11 views
22

Necesito el objeto (o "objeto singleton" u "objeto complementario" ... cualquier cosa menos la clase) definido por un nombre de cadena. En otras palabras, si tiene:Obteniendo instancia de objeto por nombre de cadena en scala

package myPackage 
object myObject 

... entonces ¿hay algo como esto:

GetSingletonObjectByName("myPackage.myObject") match { 
    case instance: myPackage.myObject => "instance is what I wanted" 
} 

Respuesta

12

Scala sigue faltando una API de reflexión. Puede obtener la una instancia del objeto acompañante mediante la carga de la clase de objeto compañera:

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) 

Para obtener el compañero sin tipo de objeto que puede utilizar la clase directamente:

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) 

Esto depende de la forma en Scala está mapeado a las clases de Java.

+1

vaca Santo. ¿Sabes si esta sintaxis es una parte fija de las especificaciones de Scala (de todos modos fijada como cualquier otra cosa en el lenguaje)? Parece una mala idea confiar en esto. Y dado que mi objetivo era hacer el código * más claro * ... ¡Gracias! – Dave

+0

Como mencionó, todavía no hay API de reflexión en Scala, así que si esto está cubierto por las especificaciones de Scala o no, esta es la única forma de hacerlo. Noté que esta pregunta/respuesta tiene más de un año, ¿hay alguna noticia aquí? – pdinklag

1

Evitando los trucos de reflexión, no se puede. Tenga en cuenta, por ejemplo, cómo se define el método companion en las colecciones de Scala 2.8: está ahí para que una instancia de una clase pueda obtener el objeto complementario, que de otro modo no sería posible.

+0

¿Podría agregar un enlace a la fuente, por favor? –

+0

http://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/src/library/scala, sin embargo, esperemos que el Scaladoc 2 de 2.8 pronto contenga enlaces a la fuente, como ya ocurre con 2.7. –

11

Ajuste a la respuesta anterior de Thomas Jung: sería mejor decir companion [List.type] porque a) esta debería ser una forma estable de referirse a ella, no depende del esquema de manipulación de nombre yb) obtienes la tipos no eliminados

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

¡Muy bonito! Todavía un poco torpe para mis gustos pero puedo usar esto ... – Dave

+0

¿Cómo es esto mejor que solo 'List.make (3," a ")'? El OP quería obtener el objeto por nombre de cadena – IttayD

+1

¡Gracias! Esto es exactamente lo que estaba buscando. Ciertamente es un truco, pero menos sucio de lo que logré. –

34

en Scala 2.10 podemos hacer como esto

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