Как реализуется `toString` в` scala.Enumeration $ Value`? - PullRequest
2 голосов
/ 27 мая 2010

У меня есть перечисление 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 в Enumeration в Scala 2.8? Я попытался найти источник Enumeration, но ничего не понял.

Ответы [ 2 ]

6 голосов
/ 27 мая 2010

Реализация основана на API отражения Java.

Если вы определяете val для значений перечисления:

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

Существуют методы для val в классе Fruit:

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 -> 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 голос
/ 27 мая 2010

В Scala 2.8.0.RC2 вы можете найти реализацию toString во внутреннем классе Val в строке 273 из Enumeration.scala. Экземпляры Val создаются с помощью метода Value в строке 192 . В настоящее время я не понимаю, как имена (Apple, Banana, ...) извлекаются. Может ли кто-нибудь помочь?

...