Scala:从集

时间:2016-05-17 19:07:37

标签: scala reflection enumeration

我想知道是否有任何方法可以从集合中创建枚举类(例如,一组字符串)。

以下是一个简单的尝试:

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(使用我假设的反射)?

1 个答案:

答案 0 :(得分:0)

TL; DR:查看底部的示例。

枚举中的值没有字符串名称(尽管它们具有唯一的数字ID)。枚举值有两种方式可以获得字符串名称:

  1. 您在致电Value时明确传递,例如Value("v1")
  2. 如果您在类中创建val字段,则Scala会从字段名称中推断出值,例如在val v1 = Value。这是通过反射内部完成的,通过检查所有返回符合类型的0-args方法。
  3. 第二种情况不适用于您的示例: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