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.
Come mai sapevo già che sarebbe stato tu a rispondere?) –
Perché c'è bisogno di trasmettere? Considero "asInstanceOf" un'ammissione di sconfitta e un bug che aspetta di accadere. –
Una notazione alternativa sarebbe: 'val TypeRef (pre, _, _) = typeOf [...]; val moduleClass = pre.typeSymbol'. –