gpt4 book ai didi

scala - 如何获得 Scala 2.10 反射引用的实际对象?

转载 作者:行者123 更新时间:2023-12-03 15:32:25 25 4
gpt4 key购买 nike

请考虑以下代码:

object ResponseType extends Enumeration {
val Listing, Album = Value
}

我可以得到 Symbol像这样引用这个对象:
import reflect.runtime.universe._
val s = typeOf[ResponseType.Value].asInstanceOf[TypeRef].pre.typeSymbol

现在,有了这个符号,我怎样才能得到实际的 ResponseType目的?

最佳答案

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

现在,一些解释是有序的,因为这是一个相当模糊的实现细节,我们(还!)无法在公共(public) API 中抽象出来。

对于每个 object Scala 创建一个代表其签名的底层类,内部称为模块类。例如,如果你编译 object C编译器将生成 C$.class .这正是模块类。

请注意,模块类与伴随类不同。比如说,对于 case class C ,编译器会生成三个符号: type C , term C和(另一个) type C , 其中第一个 type C表示 C 类(包含自动生成的副本、productPrefix、productArity 等)和第二个 type C表示对象 C 的签名(其中包含自动生成的工厂、提取器等)。不会有任何名称冲突,因为模块类没有直接添加到符号表中,只能通过 <module>.moduleClass 获得。 .

所以你实际上从你的 typeOf[ResponseType.Value].asInstanceOf[TypeRef].pre.typeSymbol得到了什么incantation 是代表模块类的符号。 API 中没有任何函数可以让您从模块类中获取模块符号。在编译器内部肯定有一个,但我们决定不公开这个实现细节,因为它很可能很快就会改变。

要访问源模块,您需要访问 owner ,查看其成员列表并在那里查找与模块类具有相同名称的对象。这正是 moduleClass.owner.typeSignature.member(moduleClass.name.toTermName)做。一个小警告是,如果在同一范围内您有一个同名的方法,那么 member将返回一个重载符号,您需要执行类似 .member(...).suchThat(_.isModule) 的操作.

之后就是小菜一碟了。

编辑。 实际上我们正在考虑引入 ClassSymbol.module这将返回模块类的源模块符号,否则返回 NoSymbol。很可能这最终会出现在 RC1 中。遵循发行说明。

关于scala - 如何获得 Scala 2.10 反射引用的实际对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12128783/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com