2012-08-26 11 views

risposta

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 

Ora, qualche spiegazione è in ordine, dal momento che questo è piuttosto un dettaglio oscura implementazione che abbiamo (ancora!) Sono riusciti a astratto su nel API pubblica.

Per ogni object Scala crea una classe sottostante che rappresenta la propria firma, internamente denominata classe modulo. Ad esempio, se si compila object C il compilatore genererà C$.class. Questa è esattamente la classe del modulo.

Si noti che le classi modulo sono diverse dalle classi companion. Supponiamo che, per case class C, il compilatore generi tre simboli: type C, term C e (altro) type C, dove il primo type C rappresenta la classe C (che contiene copia generata automaticamente, productPrefix, productArity ecc.) E il secondo type C rappresenta una firma dell'oggetto C (che contiene fabbrica generata automaticamente, estrattore, ecc.). Non ci saranno conflitti di nomi, poiché la classe del modulo non viene aggiunta direttamente alla tabella dei simboli ed è disponibile solo tramite <module>.moduleClass.


Quindi quello che effettivamente ottenere dal vostro typeOf[ResponseType.Value].asInstanceOf[TypeRef].pre.typeSymbol incantesimo è un simbolo che si distingue per una classe modulo. Non c'è alcuna funzione nell'API che ti possa portare a un simbolo di modulo da una classe di modulo. All'interno del compilatore ce ne è sicuramente uno, ma abbiamo deciso di non esporre questo dettaglio di implementazione, perché potrebbe presto cambiare molto.

Per arrivare a un modulo sorgente è necessario andare a owner, dare un'occhiata all'elenco dei suoi membri e cercare un oggetto con lo stesso nome della classe del modulo. Questo è esattamente ciò che fa moduleClass.owner.typeSignature.member(moduleClass.name.toTermName). Un piccolo avvertimento è che se nello stesso ambito si ha un metodo con lo stesso nome, allora member restituirà un simbolo sovraccarico, e sarà necessario fare qualcosa come .member(...).suchThat(_.isModule).

Dopo questo è un pezzo di torta.


Modifica. In realtà stiamo pensando di introdurre ClassSymbol.module che restituirebbe il simbolo del modulo di origine per una classe di modulo e altrimenti NoSymbol. Molto probabilmente questo finirà in RC1. Segui le note di rilascio.

+0

Come mai sapevo già che sarebbe stato tu a rispondere?) –

+3

Perché c'è bisogno di trasmettere? Considero "asInstanceOf" un'ammissione di sconfitta e un bug che aspetta di accadere. –

+0

Una notazione alternativa sarebbe: 'val TypeRef (pre, _, _) = typeOf [...]; val moduleClass = pre.typeSymbol'. –

Problemi correlati