我的问题是如何使用Scala reflection package
在Scala中定义对象中的内部对象?
object Units {
val values = CITIZEN :: WORKER :: Nil // I need something reflectional to list all of the case objects
case object CITIZEN extends Population
case object WORKER extends Population
}
答案 0 :(得分:5)
有很多方法可以做到这一点,但为了性能和(更重要的)类型安全性,我建议在运行时反射中使用宏(编译时反射)。
这是一个使用宏的快速实现:
import scala.language.experimental.macros
object MacroUtils {
import scala.reflect.macros.Context
def values = macro MacroUtils.values_impl
def values_impl(c: Context) = {
import c.universe._
val objs = c.enclosingClass.collect {
case ModuleDef(mods, name, _) if mods hasFlag Flag.CASE => Ident(name)
}
c.Expr[List[Any]](
Apply(Select(reify(List).tree, newTermName("apply")), objs.toList)
)
}
}
trait Population
object Units {
val values = MacroUtils.values
case object CITIZEN extends Population
case object WORKER extends Population
}
然后,例如:
scala> val populations: List[Population] = Units.values
populations: List[Population] = List(CITIZEN, WORKER)
请注意,编译器知道可以将case对象列表静态地键入为人口列表。
答案 1 :(得分:1)
我不确定这是否是最好的方法,但现在是:
object Units {
val values = CITIZEN :: WORKER :: Nil
trait Population
case object CITIZEN extends Population
case object WORKER extends Population
val reflectionValues = {
import scala.reflect.runtime.{universe => ru}
val mirror = ru.runtimeMirror(getClass.getClassLoader)
val objects = ru.typeOf[Units.type].declarations.filter(_.isModule)
objects.map(o => mirror.reflectModule(o.asModule).instance.asInstanceOf[Population]).toList
}
def main(args: Array[String]) {
assert(values == reflectionValues)
}
}