2012-08-26 4 views

Antwort

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 

Nun ist eine Erklärung in Ordnung, da dieses Detail durchaus ein obskure Implementierung ist, dass wir (noch!) Haben in der Öffentlichkeit API abstrahieren über nicht in der Lage gewesen.

Für jede object Scala erstellt eine zugrunde liegende Klasse, die seine Signatur darstellt, intern Modulklasse genannt. Wenn Sie beispielsweise object C kompilieren, generiert der Compiler C$.class. Das ist genau die Modulklasse.

Beachten Sie, dass Modulklassen sich von Companion-Klassen unterscheiden. Angenommen, für case class C erzeugt der Compiler drei Symbole: type C, term C und (ein anderer) type C, wobei die erste type C die Klasse C (die automatisch generierte Kopien, productPrefix, productArity usw. enthält) darstellt und die zweite type C eine Signatur darstellt von Objekt C (das automatisch generierte Fabrik, Extraktor usw. enthält). Es wird keine Namenskonflikte geben, da die Modulklasse nicht direkt zur Symboltabelle hinzugefügt wird und nur über <module>.moduleClass verfügbar ist.


Also, was Sie eigentlich von Ihrer typeOf[ResponseType.Value].asInstanceOf[TypeRef].pre.typeSymbol Beschwörung erhalten, ist ein Symbol, das für eine Modulklasse steht. In der API gibt es keine Funktion, mit der Sie von einer Modulklasse zu einem Modulsymbol gelangen. Intern im Compiler gibt es sicherlich einen, aber wir haben uns entschieden, dieses Implementierungsdetail nicht zu veröffentlichen, weil es sich sehr bald ändern könnte.

Um zu einem Quellmodul zu gelangen, müssen Sie zu owner gehen, einen Blick in die Liste seiner Mitglieder werfen und dort ein Objekt suchen, das denselben Namen wie die Modulklasse hat. Genau das tut . Ein kleiner Vorbehalt ist, dass, wenn Sie im selben Bereich eine Methode mit demselben Namen haben, member ein überladenes Symbol zurückgibt und Sie so etwas wie .member(...).suchThat(_.isModule) machen müssen.

Danach ist es ein Stück Kuchen.


Bearbeiten. Eigentlich denken wir über die Einführung von ClassSymbol.module nach, die andernfalls das Quellenmodulsymbol für eine Modulklasse und ein NoSymbol zurückgeben würde. Wahrscheinlich wird dies in RC1 enden. Befolgen Sie die Versionshinweise.

+0

Wie kommt es, dass ich bereits wusste, dass Sie das beantworten sollten?) –

+3

Warum ist es notwendig zu werfen? Ich betrachte 'asInstanceOf' als Eingeständnis der Niederlage, und einen Fehler, der darauf wartet, passiert zu sein. –

+0

Eine alternative Schreibweise wäre: 'val TypeRef (pre, _, _) = typeOf [...]; val moduleClass = pre.typeSymbol'. –

Verwandte Themen