Scala反射非常複雜。它包含類型符號和鏡像。你能告訴我他們之間的關係嗎?類型符號和Scala反射鏡之間的關係
回答
在使用Scala Reflection API時,如果您使用了Java反射API,您會遇到更多類型的用法。鑑於你開始用含有類的完全限定類名稱的String
的示例場景,這些都是你很可能會遇到類型:
Universe:斯卡拉支持運行時和編譯時反射。通過從相應的Universe導入,您可以選擇您正在進行的反射。對於運行時反射,這對應於
scala.reflect.runtime
包,對於編譯時反射它對應於scala.reflect.macros
包。這個答案關注前者。與Java一樣,您通常會通過選擇要反映的ClassLoader的類來啓動任何反射。 Scala提供了一個使用當前類的
ClassLoader
的快捷方式:scala.reflect.runtime.currentMirror
,這會給你一個Mirror
(稍後的更多鏡像)。許多JVM應用程序只使用一個類加載器,所以這是Scala Reflection API的一個常用入口點。由於您從runtime
導入,您現在處於該宇宙中。Symbols:符號包含關於您想要反映的任何靜態元數據。這包括任何你能想到的:這是一個case類,它是一個字段,是一個類,什麼是類型參數,是抽象的等等。你可能不會查詢任何可能依賴於當前詞法範圍的東西,例如一個班級有什麼成員。您也可能無法以任何方式與您反思的內容進行交互(如訪問字段或調用方法)。你可以查詢元數據。
一個班級的成員如何隨詞彙範圍而變化?想象一下帶有單個
def foo: String
的抽象類。名稱foo
可能在一個上下文中綁定到def
(如果您查詢它,則會給出MethodSymbol
),或者可能在另一個上下文(給出TermSymbol
)時將其綁定到val
。當使用符號的工作是很常見明確必須聲明你期待什麼樣的符號,你通過這些方法.asTerm
,.asMethod
,.asClass
等繼續,我們開始與
String
例子做到這一點。您可以使用Mirror
推導出描述類的ClassSymbol
:currentMirror.staticClass(myString)
。Types:類型允許您查詢有關符號在當前詞彙上下文中引用的類型的信息。您通常使用
Type
來做兩件事:查詢哪些變量,vals和defs,以及查詢類型關係(例如,此類型是該類型的子類)。有兩種方法可以獲得Type
。通過TypeSymbol
(ClassSymbol
是TypeSymbol
)或通過TypeTag
。繼續這個例子,你將調用
.toType
方法來得到Type
的符號。Scopes:當你問一個
Type
爲.members
或.decl
- 這是什麼讓你條件(VAR和丘壑)和方法,你得到的Symbol
S中的成員在當前詞法範圍的列表。此列表保存在MemberScope
類型中,它只是一個榮耀的List[Symbol]
。在我們上面的抽象類的示例中,取決於當前範圍,此列表將包含名稱
foo
的TermSymbol
或MethodSymbol
。- Names:名稱有兩種口味:
TermName
和TypeName
。它只是一個String
的包裝。您可以使用該類型來確定由任何Name
命名的內容。 - Mirrors:最後鏡子是你用來與「某物」交互的東西。您通常從
Symbol
開始,然後使用該符號爲要與之交互的方法,構造函數或字段派生符號。當你有你需要的符號時,你使用currentMirror
爲這些符號創建鏡像。通過鏡像,您可以調用構造函數(ClassMirror
),訪問字段(FieldMirror
)或調用方法(MethodMirror
)。您不能使用鏡像來查詢關於所反映事物的元數據。
所以把一個例子一起反映上面的描述中,這是你如何將搜索領域,調用構造函數和閱讀val
,給出完全限定類名String
:
// 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"
- 1. 反射類型和類型描述符
- 2. TypeRep與「類型」GADT之間的關係
- 3. GraphViewer類和GraphEditorViewer類之間的關係
- 4. 反射和泛型類型
- 5. 視圖和模型之間的關係
- 6. 關於鏡面反射的問題
- 7. System.Object類和Structs之間的關係
- 8. char *和UBYTE *之間的類型轉換*(無符號字符*)
- 9. 什麼是「視場」和「透鏡長度」之間的關係
- 10. 類之間的關係
- 11. 類之間的關係
- 12. 模型和映射關係
- 13. 與Flask-SQLAlchemy和反射的關係
- 14. 拆箱類型和嚴格性之間的關係是什麼?
- 15. Scala中的匹配類型符號
- 16. Scala複製和反射
- 17. 創建用戶,類型和類型標題表之間的關係
- 18. RMI和反射之間的區別
- 19. 如何映射多個繼承模型之間的關係?
- 20. scala反射:getDeclaringTrait?
- 21. Scala的反射API
- 22. 不同模型類型之間的不同關係Laravel
- 23. Scala和C++特徵之間有什麼關係
- 24. JRuby:Java和Ruby類型/類之間的映射/轉換的文檔?
- 25. 鋰的mongodb模型之間的關係
- 26. Scala的存在類型和Java的通配符之間的區別?
- 27. 從方法簽名獲取arg類型(鏡像/反射/自檢?)
- 28. LLVM IR指令和源代碼行之間的映射關係
- 29. 如何獲取使用Scala反射的方法的返回類型字符串?
- 30. 兩種型號之間的關聯