【问题标题】:How can I get the actual object referred to by Scala 2.10 reflection?如何获得 Scala 2.10 反射所引用的实际对象?
【发布时间】:2012-08-26 08:45:58
【问题描述】:

请考虑以下代码:

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

我可以像这样得到引用这个对象的Symbol

import reflect.runtime.universe._
val s = typeOf[ResponseType.Value].asInstanceOf[TypeRef].pre.typeSymbol

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

【问题讨论】:

    标签: scala reflection scala-2.10


    【解决方案1】:
    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
    

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

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

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


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

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

    之后就是小菜一碟了。


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

    【讨论】:

    • 为什么需要强制转换?我认为asInstanceOf 是承认失败,一个等待发生的错误。
    • 另一种表示法是:val TypeRef(pre, _, _) = typeOf[...]; val moduleClass = pre.typeSymbol
    猜你喜欢
    • 2013-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 2012-06-30
    • 1970-01-01
    相关资源
    最近更新 更多