Как добавить многоразовое поле в Scala Enumeration?

Я хотел бы расширить реализацию Scala Enumeration с помощью настраиваемого поля, например label. Это новое поле должно быть доступно через values этого перечисления. Кроме того, это настраиваемое поле должно быть частью различных реализаций Enumeration.

Мне известны следующие вопросы в Stackoverflow:

Однако ни один из них не решает мои проблемы:

Первая проблема заключается в том, что я могу добавить настраиваемое поле. Однако я не могу получить доступ к этому дополнительному полю через Values, возвращаемый Enumeration.values. Следующий код работает и печатает 2nd enumeration value:

object MyEnum extends Enumeration {
  type MyEnum = MyVal
  val VALUE_ONE = MyVal()
  val VALUE_TWO = MyVal(Some("2nd enumeration value"))
  val VALUE_THREE = MyVal(Some("3rd value"))

  case class MyVal(label: Option[String] = None) extends Val(nextId)
}
import MyEnum._

println(VALUE_TWO.label.get)

Обратите внимание, что я обращаюсь к метке через одно из значений. Следующий код не работает:

for (value <- MyEnum.values) println(value.label)

Сообщение об ошибке выглядит следующим образом: error: value label is not a member of MyEnum.Value

Очевидно, что вместо MyEnum.MyVal используется MyEnum.Val. Последний не определяет label, в то время как мое настраиваемое значение будет содержать поле label.

Вторая проблема заключается в том, что кажется возможным ввести пользовательские Value и Val, соответственно, только в контексте Enumeration. Таким образом, насколько мне известно, такое поле невозможно использовать в разных перечислениях. По крайней мере, следующий код не компилируется:

case class MyVal(label: Option[String] = None) extends Enumeration.Val(nextId)

object MyEnum extends Enumeration {
  type MyEnum = MyVal
  val VALUE_ONE = MyVal()
  val VALUE_TWO = MyVal(Some("2nd enumeration value"))
}

object MySecondEnum extends Enumeration {
  type MySecondEnum = MyVal
  val VALUE_ONE = MyVal()
  val VALUE_TWO = MyVal(Some("2nd enumeration value"))
}

Из-за того, что класс Val защищен, класс MyVal не может получить доступ Val - MyVal не определен в контексте перечисления.

Есть идеи, как решить вышеуказанные проблемы?


person Martin    schedule 28.04.2014    source источник


Ответы (1)


Первая проблема решается недавним вопросом, моим ответом, на который мне не понравилось.

Для этого случая использования я бы написал собственный метод widgets с полезным типом, но мой связанный ответ, который просто вводит неявное преобразование, кажется довольно удобным. Не знаю, почему это не каноническое решение.

Что касается второй проблемы, ваш производный MyVal должен просто реализовать черту.

Образец:

scala> trait Labelled { def label: Option[String] }
defined trait Labelled

scala> object A extends Enumeration { case class AA(label: Option[String]) extends Val with Labelled ; val X = AA(Some("one")) }
defined object A

scala> object B extends Enumeration { case class BB(label: Option[String]) extends Val with Labelled ; val Y = BB(None) }
defined object B

scala> val labels = List(A.X, B.Y)
labels: List[Enumeration#Val with Product with Labelled] = List(X, Y)

scala> labels map (_.label)
res0: List[Option[String]] = List(Some(one), None)
person som-snytt    schedule 28.04.2014