2016-05-17 71 views
2

我想知道是否有任何方法可以從一組(例如,一組字符串)創建枚舉類。Scala:從一組創建枚舉對象

下面是一個簡單的嘗試:

val s = Set("v1", "v2", "v3") 

object sEnum extends Enumeration { 
    for (v <- s) { 
    val v = Value 
    } 
} 

for (v <- sEnum.values) { 
    println(v) 
} 

枚舉對象看起來編譯,但它的值是靠不住的:打印循環顯示,內sEnum值是這樣的:

<無效的枚舉:沒有字段爲#0>

因此,問題似乎是在值聲明

val v = Value 

有什麼方法可以用運行時的內容替換變量v(使用我認爲的反射)?

回答

0

TL; DR:看看底部的例子。

enum中的值沒有字符串名稱(儘管它們具有唯一的數字ID)。有兩種方法的枚舉值怎麼能得到一個字符串名稱:調用Value

  1. 你把它傳遞明確,例如Value("v1")
  2. 如果您在該類中創建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