如何实现`scala.Enumeration $ Value`中的`toString`?

时间:2010-05-27 05:58:57

标签: scala enumeration

我将枚举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

我的问题是:

Scala 2.8中toString中的方法Enumeration如何实现?我试着查看Enumeration的来源,但无法理解任何内容。

2 个答案:

答案 0 :(得分:6)

该实现基于Java反射API。

如果为枚举值定义val:

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

在Fruit类中有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,并从地图中检索名称为枚举值的名称。

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()

如果您定义这样的枚举,则可以轻松破解此实现:

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)

答案 1 :(得分:1)

在Scala 2.8.0.RC2中,您可以在toString Val的内部类Enumeration.scala中找到Val的实现。 Value的实例通过line 273中的Apple, Banana, ...方法进行实例化。目前我不明白如何提取名称({{1}})。有人可以帮忙吗?