lxy*_*lxy 4 reflection types symbols scala mirror
Scala反射非常复杂.它包含类型符号和镜像.你能告诉我他们之间的关系吗?
gog*_*tad 11
使用Scala Reflection API时,如果使用Java Reflection API,则会遇到更多类型的内容.给出一个示例场景,您从String包含类的完全限定类名开始,这些是您可能遇到的类型:
Universe:Scala支持运行时和编译时反射.您可以通过从相应的Universe导入来选择正在执行的反射.对于运行时反射,这对应于scala.reflect.runtime包,对于编译时反射它对应于scala.reflect.macros包.这个答案集中在前者身上.
与Java一样,您通常可以通过选择要反映的ClassLoader类来开始任何反射.Scala提供了使用ClassLoader当前类的快捷方式:scala.reflect.runtime.currentMirror这为您提供了一个Mirror(稍后将更多关于镜像).许多JVM应用程序只使用一个类加载器,因此这是Scala Reflection API的常见入口点.既然你现在正在从runtime那个宇宙进口.
符号:符号包含有关您想要反映的内容的静态元数据.这包括你能想到的任何东西:这是一个案例类,它是一个字段,它是一个类,什么是类型参数,它是抽象的等等你可能不会查询任何可能取决于当前词法范围的东西,例如一个班级的成员.您也可能无法以任何方式与您反映的事物进行交互(例如访问字段或调用方法).您只需查询元数据即可.
一个班级的成员如何根据词汇范围而变化?想象一下一个单一的抽象类def foo: String.该名称foo可能绑定到def一个上下文(给你一个你MethodSymbol应该查询它)或它可以绑定到val另一个上下文(给你一个TermSymbol).当使用符号的工作是很常见明确必须声明你期待什么样的符号,你通过这些方法做到这一点.asTerm,.asMethod,.asClass等.
继续String我们开始的例子.您使用它Mirror来派生ClassSymbol描述类:currentMirror.staticClass(myString).
类型:类型允许您查询有关符号在当前词法上下文中引用的类型的信息.您通常将Types用于两件事:查询vars,vals和defs,以及查询类型关系(例如,此类型是该类型的子类).掌握一种方法有两种方法Type.通过TypeSymbol(ClassSymbol是aTypeSymbol)或通过aTypeTag.
继续这个例子,你将.toType在你得到的符号上调用方法Type.
范围:当你问一个Type对.members或.decl-这是什么让你条件(VAR和丘壑)和方法,你得到的名单Symbol在当前词法范围成员秒.这个列表保存在一个类型中MemberScope,它只是一个美化List[Symbol].
在我们上面使用抽象类的示例中,此列表将根据当前范围包含a TermSymbol或a MethodSymbol名称foo.
TermName和TypeName.它只是一个包装String.您可以使用该类型来确定any命名的内容Name.Symbol,然后使用该符号为您想要与之交互的方法,构造函数或字段派生符号.如果您有所需的符号,则可以使用currentMirror这些符号创建镜像.Mirrors允许您调用构造函数(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"
Run Code Online (Sandbox Code Playgroud)