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
ここで、いくつかの説明が必要です。これは、公開 API で (まだ!) 抽象化できていない非常にあいまいな実装の詳細であるためです。
For every Scala は、内部的にmodule classobject
と呼ばれる、その署名を表す基礎となるクラスを作成します。たとえば、コンパイラをコンパイルすると、 . それがまさにモジュールクラスです。object C
C$.class
モジュール クラスはコンパニオン クラスとは異なることに注意してください。の場合、コンパイラは,と (別の) のcase class C
3 つのシンボルを生成します。最初のシンボルはクラス C (自動生成されたコピー、productPrefix、productArity などを含む) を表し、2 番目のシンボルはオブジェクト C の署名 (含む) を表します。自動生成されたファクトリ、エクストラクタなど)。モジュール クラスはシンボル テーブルに直接追加されず、 を通じてのみ使用できるため、名前の衝突はありません。type C
term C
type C
type C
type C
<module>.moduleClass
したがって、呪文から実際に得られるtypeOf[ResponseType.Value].asInstanceOf[TypeRef].pre.typeSymbol
のは、モジュール クラスを表すシンボルです。API には、モジュール クラスからモジュール シンボルを取得する関数はありません。コンパイラの内部には確かに 1 つ存在しますが、この実装の詳細は公開しないことにしました。
ソース モジュールにアクセスするにはowner
、 に移動し、そのメンバーのリストを調べて、モジュール クラスと同じ名前のオブジェクトを検索します。まさにそれmoduleClass.owner.typeSignature.member(moduleClass.name.toTermName)
です。マイナーな注意点の 1 つは、同じスコープ内に同じ名前のメソッドがある場合member
、オーバーロードされたシンボルが返されるため、.member(...).suchThat(_.isModule)
.
その後は簡単です。
編集。ClassSymbol.module
実際には、モジュール クラスの場合はソース モジュール シンボルを返し、それ以外の場合は NoSymbol を返すように導入することを考えています。おそらくこれは RC1 で終わるでしょう。リリースノートに従ってください。