2012-08-26 16 views

Respuesta

13
scala> val moduleClass = typeOf[ResponseType.Value].asInstanceOf[TypeRef].pre.typeSymbol 
moduleClass: reflect.runtime.universe.Symbol = object ResponseType 

scala> val module = moduleClass.owner.typeSignature.member(moduleClass.name.toTermName) 
module: reflect.runtime.universe.Symbol = object ResponseType 

scala> reflect.runtime.currentMirror.reflectModule(module.asModule).instance 
res9: Any = ResponseType 

Ahora, alguna explicación está en orden, ya que esto es todo un detalle oscuro aplicación que hemos (todavía!) Han podido abstracto sobre la API pública.

Por cada object Scala crea una clase subyacente que representa su firma, internamente llamada módulo clase. Por ejemplo, si compila object C, el compilador generará C$.class. Esa es exactamente la clase de módulo.

Tenga en cuenta que las clases de módulo son diferentes de las clases complementarias. Digamos, para case class C, el compilador generará tres símbolos: type C, term C y (otro) type C, donde el primer type C representa la clase C (que contiene copia autogenerada, productPrefix, productArity, etc.) y el segundo type C representa una firma del objeto C (que contiene fábrica autogenerada, extractor, etc.). No habrá ningún conflicto de nombres, porque la clase de módulo no se agrega directamente a la tabla de símbolos y solo está disponible a través del <module>.moduleClass.


Así que lo que realmente recibe de su typeOf[ResponseType.Value].asInstanceOf[TypeRef].pre.typeSymbol encantamiento es un símbolo que representa una clase de módulo. No hay función en la API que lo lleve a un símbolo de módulo de una clase de módulo. Internamente en el compilador seguramente hay uno, pero decidimos no exponer este detalle de implementación, porque muy bien podría cambiar pronto.

Para acceder a un módulo fuente, debe ir al owner, eche un vistazo a la lista de sus miembros y busque un objeto que tenga el mismo nombre que la clase de módulo. Eso es exactamente lo que hace moduleClass.owner.typeSignature.member(moduleClass.name.toTermName). Una advertencia menor es que si en el mismo ámbito tiene un método con el mismo nombre, entonces member devolverá un símbolo sobrecargado, y tendrá que hacer algo como .member(...).suchThat(_.isModule).

Después de eso, es un pedazo de pastel.


Editar. En realidad, estamos pensando en introducir ClassSymbol.module que devolvería el símbolo del módulo fuente para una clase de módulo y NoSymbol en caso contrario. Es muy probable que esto termine en RC1. Sigue las notas de la versión.

+0

¿Cómo es que ya sabía que sería usted para responder eso?) –

+3

¿Por qué hay necesidad de lanzar? Considero 'asInstanceOf' una admisión de derrota, y un error esperando a suceder. –

+0

Una notación alternativa sería: 'val TypeRef (pre, _, _) = typeOf [...]; val moduleClass = pre.typeSymbol'. –

Cuestiones relacionadas