【问题标题】:Using Scala 2.10 reflection how can I list the values of Enumeration?使用 Scala 2.10 反射如何列出枚举的值?
【发布时间】:2012-08-26 09:54:48
【问题描述】:

有以下枚举

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

如何获得其 val 的列表?

【问题讨论】:

    标签: scala reflection enumeration scala-2.10


    【解决方案1】:

    如果您想彻底了解这一点,您需要检查您的符号是否具有 Value 作为超类型:

    def valueSymbols[E <: Enumeration: TypeTag] = {
      val valueType = typeOf[E#Value]
      typeOf[E].members.filter(sym => !sym.isMethod &&
        sym.typeSignature.baseType(valueType.typeSymbol) =:= valueType
      )
    }
    

    现在,即使您有以下条件(这是完全合法的):

    object ResponseType extends Enumeration {
      val Listing, Album = Value
      val someNonValueThing = "You don't want this in your list of value symbols!"
    }
    

    你仍然得到正确答案:

    scala> valueSymbols[ResponseType.type] foreach println
    value Album
    value Listing
    

    您当前的方法将在此处包括value someNonValueThing

    【讨论】:

    • 确实很合理。谢谢
    • 请注意,Enumeration#Value 的类型别名与上述过滤谓词匹配。要解决此问题,请查看! sym.isType
    【解决方案2】:

    以下代码获取代表“vals”的Symbol对象列表:

    import reflect.runtime.universe._ // Access the reflection api
    
    typeOf[ResponseType.Value]  //  - A `Type`, the basic unit of reflection api
      .asInstanceOf[TypeRef]    //  - A specific kind of Type with knowledge of
                                //    the place it's being referred from
      .pre                      //  - AFAIK the referring Type
      .members                  //  - A list of `Symbol` objects representing
                                //    all members of this type, including 
                                //    private and inherited ones, classes and 
                                //    objects - everything.
                                //    `Symbol`s are the second basic unit of 
                                //    reflection api.
      .view                     //  - For lazy filtering
      .filter(_.isTerm)         //  - Leave only the symbols which extend the  
                                //    `TermSymbol` type. This is a very broad 
                                //    category of symbols, which besides values
                                //    includes methods, classes and even 
                                //    packages.
      .filterNot(_.isMethod)    //  - filter out the rest
      .filterNot(_.isModule)
      .filterNot(_.isClass)
      .toList                   //  - force the view into a final List
    

    应该注意的是,可以通过.collect 测试特定类型来实现,而不是过滤 is 子句,如下所示:

    .collect{ case symbol : MethodSymbol => symbol }
    

    反射 api 中的其他任务可能需要这种方法。

    还应该注意,使用.view 根本不是强制性的,它只是使用一系列filter 应用程序(与mapflatMap 等许多其他功能一样多) .) 更有效,通过只遍历输入集合一次并且在它实际上被强制进入某个具体集合的点(在我们的例子中为.toList)。

    更新

    正如 Travis Brown 所建议的,也可以直接引用 ResponseType 对象。所以typeOf[ResponseType.Value].asInstanceOf[TypeRef].pre部分可以换成typeOf[ResponseType.type]

    【讨论】:

    • 为什么不直接使用typeOf[ResponseType.type].members...?如果不讨论动机,你的约束就会显得有些武断。
    • @TravisBrown 因为这些 val 不是 typeOf[ResponseType.Value] 的成员,这就是重点
    • 不是,但他们是ResponseType 的成员。
    • @TravisBrown 对不起。没有注意到你有 ResponseType .type 那里。这显然是一个不错的解决方案。我已经更新了答案以包含它
    • 这种方法仍然存在潜在问题——请参阅my answer
    【解决方案3】:

    您可以通过返回的集合迭代枚举的值 枚举值方法:

    scala> for (e <- ResponseType.values) println(e)
    Listing
    Album
    

    【讨论】:

    • 很抱歉,问题是关于使用反射的。
    猜你喜欢
    • 2012-03-18
    • 1970-01-01
    • 2017-11-07
    • 1970-01-01
    • 1970-01-01
    • 2019-10-29
    • 1970-01-01
    • 2013-06-04
    • 1970-01-01
    相关资源
    最近更新 更多