2

トレイトがサード パーティによって実装されている (プラグイン アーキテクチャを考えてください) という非常にまれなユース ケースがあり、各トレイトのコンパニオン オブジェクトのフィールドを取得したいと考えています。

シンプルなトレイトの実装は次のようになります。

trait Plugin {
  val ID: String
}
class HelloWorldPlugin extends Plugin {
  val ID = HelloWorldPlugin.ID
}

object HelloWorldPlugin {
  val ID = "hello world"
}

IDプラグイン レジストリで、各プラグインの を取得したいと思います。型の消去を扱っているので、リフレクションが唯一の選択肢のようです。私は無駄に次のことを試しました:

object CompanionReflectionDemo {
  import scala.reflect.runtime.{universe => ru}
  private lazy val universeMirror = ru.runtimeMirror(getClass.getClassLoader)

  def registerPlugin[T <: Plugin](implicit tt: ru.TypeTag[T])  = {
    val companionMirror = universeMirror.reflectModule(ru.typeOf[T].typeSymbol.companion.asModule)
    val m = universeMirror.reflect(companionMirror.instance)
    val field = m.reflectField(ru.typeOf[T].decl(ru.TermName("ID")).asTerm.accessed.asTerm)
    field.get
  }

  def main(args: Array[String]) {
    val x = registerPlugin[HelloWorldPlugin]
    println(x) // expecting "hello world"
  }
}

しかし、ここでの問題は、typeOf[T]常に Module タイプではなく Class タイプを返すことです。したがって、次のランタイム エラーが発生します。

Exception in thread "main" scala.ScalaReflectionException: expected a member of object HelloWorldPlugin, you provided value org.reflect.HelloWorldPlugin.ID
    at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$abort(JavaMirrors.scala:115)
    at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$ErrorNotMember(JavaMirrors.scala:121)
    at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$scala$reflect$runtime$JavaMirrors$JavaMirror$$checkMemberOf$1.apply(JavaMirrors.scala:214)
    at scala.reflect.runtime.JavaMirrors$JavaMirror.ensuringNotFree(JavaMirrors.scala:204)
    at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$checkMemberOf(JavaMirrors.scala:213)
    at scala.reflect.runtime.JavaMirrors$JavaMirror$JavaInstanceMirror.reflectField(JavaMirrors.scala:236)
    at scala.reflect.runtime.JavaMirrors$JavaMirror$JavaInstanceMirror.reflectField(JavaMirrors.scala:233)
    at org.reflect.CompanionReflectionDemo$.registerPlugin(Blah.scala:21)
    at org.reflect.CompanionReflectionDemo$.main(Blah.scala:26)

IDから各プラグインの値を取得する最良の方法は何TypeTagですか?

4

1 に答える 1