使用Scala 2.10反射如何列出Enumeration的值?

时间:2012-08-26 09:54:48

标签: scala reflection enumeration scala-2.10

进行以下枚举

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

如何获取其vals列表?

3 个答案:

答案 0 :(得分:16)

如果您想彻底了解这一点,您需要检查您的符号是否为{超级类型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

答案 1 :(得分:7)

以下代码获取表示“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

应该注意的是,不是对is-clauses进行过滤,而是可以使用.collect测试特定类型来实现,如下所示:

.collect{ case symbol : MethodSymbol => symbol }

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

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

更新

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

答案 2 :(得分:2)

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

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