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

发布于 2024-09-02 18:41:51 字数 660 浏览 6 评论 0原文

我有一个枚举 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

我的问题是:

方法 toString 是怎样的Scala 2.8 中的 Enumeration 中的 实现了吗?我尝试查看 Enumeration 的来源,但无法理解任何内容。

I have an enum Fruit defined as:

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

Now printing values of this enum, on Scala 2.7.x gives:

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

However the same operation on Scala 2.8 gives:

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

My question is:

How is the method toString in Enumeration in Scala 2.8 implemented? I tried looking into the source of Enumeration but couldn't understand anything.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

久夏青 2024-09-09 18:41:52

在 Scala 2.8.0.RC2 中,您可以在 Enumeration.scala 的第 273 行Val 的实例通过 第 192 行。目前我不明白如何提取名称(Apple、Banana、...)。有人可以帮忙吗?

In Scala 2.8.0.RC2 you can find the implementation of toString in the inner class Val in line 273 of Enumeration.scala. The instances of Val are instantiated through the Value method in line 192. Currently I don't understand how the names (Apple, Banana, ...) are extracted. May somebody can help out?

此岸叶落 2024-09-09 18:41:51

该实现基于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 并使用枚举值的 id 从地图中检索名称。

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
}

This Fruit.value 返回 object$Fruit.ValueSet(x, B, C) 而不是 object$Fruit.ValueSet(A, B,C)

The implementation is based on the Java reflection API.

If you define val for the enum values:

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

There are methods for the val in the class Fruit:

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

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

toString calls Enumeration.this.nameOf(i) if the name is not explicitly set. This method will try to find all methods in the enumeration class returning Value instances.

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

These are the methods of the Fruit class.

It then takes the name of the methods and the ids of enum values to build a map id -> name and retrieves the name from the map with the id of enum value.

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

This implementation can be easily broken if you define a enum like this:

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

This Fruit.value returns object$Fruit.ValueSet(x, B, C) not object$Fruit.ValueSet(A, B, C).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文