2010-05-27 21 views
2

我有限定一個枚舉Fruit爲:

object Fruit extends Enumeration { 
    val Apple, Banana, Cherry = Value 
} 

立即印刷該枚舉值,上的Scala 2.7.x給出:

scala> Fruit foreach println 
line1$object$$iw$$iw$Fruit(0) 
line1$object$$iw$$iw$Fruit(1) 
line1$object$$iw$$iw$Fruit(2) 

然而上的Scala 2.8相同的操作,得到:

scala> Fruit foreach println  
warning: there were deprecation warnings; re-run with -deprecation for details 
Apple 
Banana 
Cherry 

我的問題是:

斯卡拉2.8中的方法toStringEnumeration中如何實現?我試圖尋找Enumeration的來源,但什麼都不明白。

回答

1

在斯卡拉2.8.0.RC2中,您可以在Enumeration.scala的內部類Val,line 273中找到toString的實現。 Val的實例通過line 192中的Value方法實例化。目前我不明白如何提取名稱(Apple, Banana, ...)。願有人能幫忙嗎?

6

該實現基於Java反射API。

如果定義爲VAL枚舉值:

object Fruit extends Enumeration { 
    val Apple, Banana, Cherry = Value 
} 

有在類水果的VAL方法:

scala> Fruit.getClass.getMethods filter (_.getName.contains("Apple")) foreach println 

public scala.Enumeration$Value line10$object$$iw$$iw$Fruit$.Apple() 

toString電話Enumeration.this.nameOf(i)如果該名稱未明確設置。此方法將嘗試查找返回Value實例的枚舉類中的所有方法。

val methods = getClass.getMethods 
for (m <- methods 
    if (classOf[Value].isAssignableFrom(m.getReturnType) && 
    !java.lang.reflect.Modifier.isFinal(m.getModifiers) && 
    m.getParameterTypes.isEmpty && 
    isValDef(m))) 

這些是Fruit類的方法。

然後,它使用枚舉值的方法和ID的名稱來構建地圖id -> name,並使用枚舉值的id從地圖中檢索名稱。

object X extends Enumeration { 
    val Y = Value 
} 
object Fruit extends Enumeration { 
    val x = X.Y 
    val A,B,C = Value 
} 

這Fruit.value返回object$Fruit.ValueSet(x, B, C)object$Fruit.ValueSet(A, B, C)

val name = m.getName 
// invoke method to obtain actual `Value` instance 
val value = m.invoke(this) 
// invoke `id` method 
val idMeth = classOf[Val].getMethod("id") 
val id: Int = idMeth.invoke(value).asInstanceOf[java.lang.Integer].intValue() 

這可以實現,如果你這樣定義一個枚舉很容易被破壞。