0

I would like to extend Scala's implementation of Enumeration with a custom field, say label. That new field should be accessible via the values of that enumeration. Furthermore, that custom field should be part of various implementations of Enumeration.

I am aware of the following questions at Stackoverflow:

However, none of them solves my issues:

The first issue is that I am able to add a custom field. However, I cannot access that additional field via the Values returned by Enumeration.values. The following code works and prints 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)

Note that I access the label via one of the values. The following code does not work:

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

The error message is as follows: error: value label is not a member of MyEnum.Value

Obviously, instead of MyEnum.MyVal, MyEnum.Val is used. The latter does not define label, while my custom value would provide field label.

The second issue is that it seems to be possible to introduce a custom Value and Val, respectively, in the context of an Enumeration only. Thus, as far as I know, it is not possible to use such a field across different enums. At least, the following code does not compile:

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

Due to the fact that class Val is protected, case class MyVal cannot access Val -- MyVal is not defined in the context of an enumeration.

Any idea how to solve the above issues?

Community
  • 1
  • 1
Martin
  • 1,875
  • 1
  • 20
  • 28

1 Answers1

2

The first issue is addressed by a recent question, my answer to which got no love.

For that use case, I would write a custom widgets method with the useful type, but my linked answer, which just introduces an implicit conversion, seems pretty handy. I don't know why it's not the canonical solution.

For the second issue, your derived MyVal should just implement a trait.

Sample:

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)
Community
  • 1
  • 1
som-snytt
  • 39,429
  • 2
  • 47
  • 129