スカラ反射は実際には複雑です。それはタイプシンボルとミラーを含んでいます。彼らの関係を教えてください。タイプシンボルとスカラ反射の関係
答えて
Scala Reflection APIを使用する場合は、Java Reflection APIを使用した場合に慣れていたより多くのタイプに遭遇します。あなたはクラスの完全修飾クラス名を含むString
で始まるシナリオ例を考えると、これらはあなたが遭遇する可能性があるタイプです:
Universe:Scalaは、両方のランタイムをサポートしており、時間の反射をコンパイルします。対応する宇宙からインポートすることによって、あなたが行っているリフレクションの種類を選択します。実行時のリフレクションでは、これは
scala.reflect.runtime
パッケージに対応します。コンパイル時のリフレクションはscala.reflect.macros
パッケージに対応します。この答えは前者に焦点を当てています。Javaのように、どのClassLoaderのクラスを反映させるかを選択することで、リフレクションを開始するのが一般的です。 Scalaは現在のクラスの
ClassLoader
を使用するためのショートカットを提供します:scala.reflect.runtime.currentMirror
、これはあなたにMirror
を与えます(ミラーについては後で詳しく説明します)。多くのJVMアプリケーションでは、単一のクラスローダしか使用しないため、これはScala Reflection APIの共通のエントリポイントです。runtime
からインポートしているので、あなたは今その宇宙にいます。Symbols:シンボルには、あなたが反映したいものについての静的メタデータが含まれています。これにはあなたが考えることができるものがすべて含まれています:この事例クラス、フィールド、クラス、型パラメータ、抽象的なものなどです。現在のレキシカルスコープに依存する可能性のあるものは問いません例えば、どのクラスのメンバであるか。また、フィールドへのアクセスやメソッドの呼び出しなど、何らかの形で反映しているものとやりとりすることはできません。メタデータを照会するだけで済みます。
クラスのメンバーはどのようにレキシカルスコープによって異なるのですか?単一のを持つ抽象クラスを想像してみてください。
foo
という名前はdef
にバインドされている場合があります(MethodSymbol
をクエリする必要があります)、別のコンテキストのval
にバインドできます(TermSymbol
)。シンボルで作業する場合、それは明示的にあなたが期待するシンボルの種類を述べることが一般的ですが、あなたは我々が始まっString
例を続ける方法.asTerm
、.asMethod
、.asClass
などを介してこれを行います。
Mirror
を使用して、currentMirror.staticClass(myString)
というクラスを表すClassSymbol
を取得します。Types:Typesでは、現在のレキシカルコンテキストでシンボルが参照する型に関する情報を照会できます。典型的には、どのような変数、val、およびdefがあるかを照会し、タイプの関係を照会すること(たとえば、このタイプはそのタイプのサブクラス)に対して、通常
Type
を使用します。Type
を入手するには2通りの方法があります。TypeSymbol
(ClassSymbol
はTypeSymbol
)またはTypeTag
です。この例を続けると、
Type
を取得したシンボルの.toType
メソッドが呼び出されます。Scopes:あなたは
.members
や.decl
- このためType
を頼むときあなたの用語(VARSとヴァルス)と与えるものである方法を、あなたは現在のレキシカルスコープ内のメンバーのSymbol
のリストを取得します。このリストは、タイプMemberScope
に保存されています。それはちょうど賞賛されたList[Symbol]
です。上記の抽象クラスの例では、このリストには、現在のスコープに応じて
foo
という名前のTermSymbol
またはMethodSymbol
が含まれます。- Names:
TermName
とTypeName
:名前は2つの種類があります。それはちょうどString
のラッパーです。この型を使用して、Name
という名前のものを判別できます。 - Mirrors:最後に、ミラーは「何か」と対話するために使用するものです。通常、
Symbol
で始まり、そのシンボルを使用して、対話したいメソッド、コンストラクタ、またはフィールドのシンボルを派生させます。必要なシンボルがある場合は、currentMirror
を使用して、これらのシンボルのミラーを作成します。ミラーを使用すると、コンストラクター(ClassMirror
)を呼び出したり、フィールド(FieldMirror
)にアクセスしたり、メソッド(MethodMirror
)を呼び出すことができます。反映されていることについてメタデータを照会するのに、ミラーを使用することはできません。
:だから、これは完全修飾クラス名を持つ// Do runtime reflection on classes loaded by current ClassLoader val currentMirror: universe.Mirror = scala.reflect.runtime.currentMirror // Use symbols to navigate to pick out the methods and fields we want to invoke // Notice explicit symbol casting with the `.as*` methods. val classSymbol: universe.ClassSymbol = currentMirror.staticClass("com.example.Foo") val constructorSymbol: universe.MethodSymbol = classSymbol.primaryConstructor.asMethod val fooSymbol: Option[universe.TermSymbol] = classSymbol.toType.members.find(_.name.toString == "foo").map(_.asTerm) // Get mirrors for performing constructor and field invocations val classMirror: universe.ClassMirror = currentMirror.reflectClass(classSymbol) val fooInstance: Foo = classMirror.reflectConstructor(constructorSymbol).apply().asInstanceOf[Foo] val instanceMirror: universe.InstanceMirror = currentMirror.reflect(fooInstance) // Do the actual invocation val fooValue: String = instanceMirror.reflectField(fooSymbol.get).get.asInstanceOf[String] println(fooValue) // Prints the value of the val "foo" of the object "fooInstance"
String
与え、あなたは、フィールドを検索コンストラクタを呼び出し、val
を読んでいました方法です、上記の説明を反映して一緒に例を置く
- 1. スカラ結合型パラメータと反射
- 2. スカラ反射型ジェネリックワイルドカードの等価性
- 3. スカラの反射。メソッドを呼び出す?
- 4. Intパラメータを使用したスカラ反射
- 5. 反射的依存関係を持つジェネリッククラス
- 6. スカラ座(ランタイム)relectionのAPIを使用して反射
- 7. 反射とソケット
- 8. 反射と
- 9. 反射とタイフレフ
- 10. 反射+関数ポインタ対オブザーバパターン
- 11. 反射とScalaの
- 12. スカラ無限反復関数
- 13. 文字変数をスカラ反射に渡す方法typecheck quasiquote?
- 14. スカラ反射 - コンストラクタが呼び出されない
- 15. Javaジェネリックと反射!
- 16. Kotlin:isAssignableFromと反射型のチェック
- 17. のC#、反射とプリミティブ型
- 18. 反射
- 19. 反射
- 20. 反射
- 21. 反射
- 22. 反射
- 23. 反射
- 24. 反射
- 25. []反射
- 26. スカラの列挙と反映
- 27. 鏡面反射に関する質問
- 28. 反射と複合プロパティ
- 29. 反射と拡張方法
- 30. 反射と再帰 - StackOverflowExceptionが