我有一个枚举Fruit定义为:
object Fruit extends Enumeration {
val Apple, Banana, Cherry = Value
}
Run Code Online (Sandbox Code Playgroud)
现在,在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)
Run Code Online (Sandbox Code Playgroud)
但是,Scala 2.8上的相同操作给出:
scala> Fruit foreach println
warning: there were deprecation warnings; re-run with -deprecation for details
Apple
Banana
Cherry
Run Code Online (Sandbox Code Playgroud)
我的问题是:
该方法是如何toString在Enumeration斯卡拉2.8实现的?我试着查看源代码,Enumeration但无法理解任何事情.
该实现基于Java反射API.
如果为枚举值定义val:
object Fruit extends Enumeration {
val Apple, Banana, Cherry = Value
}
Run Code Online (Sandbox Code Playgroud)
在Fruit类中有val的方法:
scala> Fruit.getClass.getMethods filter (_.getName.contains("Apple")) foreach println
public scala.Enumeration$Value line10$object$$iw$$iw$Fruit$.Apple()
Run Code Online (Sandbox Code Playgroud)
toStringEnumeration.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)))
Run Code Online (Sandbox Code Playgroud)
这些是Fruit类的方法.
然后,它使用方法的名称和枚举值的id来构建映射id -> name,并从id为enum值的映射中检索名称.
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()
Run Code Online (Sandbox Code Playgroud)
如果您定义这样的枚举,则可以轻松地破坏此实现:
object X extends Enumeration {
val Y = Value
}
object Fruit extends Enumeration {
val x = X.Y
val A,B,C = Value
}
Run Code Online (Sandbox Code Playgroud)
这个Fruit.value object$Fruit.ValueSet(x, B, C)不返回object$Fruit.ValueSet(A, B, C).
| 归档时间: |
|
| 查看次数: |
1968 次 |
| 最近记录: |