我想知道是否有任何方法可以从集合中创建枚举类(例如,一组字符串)。
以下是一个简单的尝试:
val s = Set("v1", "v2", "v3")
object sEnum extends Enumeration {
for (v <- s) {
val v = Value
}
}
for (v <- sEnum.values) {
println(v)
}
枚举对象似乎是编译的,但它的值很难看:打印循环显示sEnum中的值如下所示:
&lt;无效的枚举:#0&gt;
没有字段
因此,问题似乎在价值声明
val v = Value
有没有办法可以在运行时用其内容替换变量v(使用我假设的反射)?
答案 0 :(得分:0)
TL; DR:查看底部的示例。
枚举中的值没有字符串名称(尽管它们具有唯一的数字ID)。枚举值有两种方式可以获得字符串名称:
Value
时明确传递,例如Value("v1")
val
字段,则Scala会从字段名称中推断出值,例如在val v1 = Value
。这是通过反射内部完成的,通过检查所有返回符合类型的0-args方法。第二种情况不适用于您的示例:val v = Value
不在类上创建方法,v
只是循环内的局部变量(隐藏迭代变量v
)。所以你需要采取第一种方法:
val s = Set("v1", "v2", "v3")
object MyEnum extends Enumeration {
s.foreach(Value(_))
}
MyEnum.values.foreach(println) // prints v1 v2 v3
现在,这不允许您轻松访问枚举值,MyEnum.v1
将无效。如何根据一组字符串值动态地将方法/字段添加到类中。至少没有一些神奇的字节码操作,你可能不想冒险。
相反,您可以定义用于检索值的自定义方法。以下是使用Symbols的示例,因此您无需使用效率低下的MyEnum.withName()
方法:
val s = Set("v1", "v2", "v3")
object MyEnum extends Enumeration {
type MyEnum = Value
s.foreach(Value(_))
private val constants = s.map(v => Symbol(v) -> withName(v)).toMap
def apply(c: Symbol): MyEnum = constants(c)
}
MyEnum.values.foreach(println) // prints v1 v2 v3
println(MyEnum('v1)) // prints v1