如何将可重用字段添加到Scala枚举?

9 浏览
0 Comments

如何将可重用字段添加到Scala枚举?

我想要在Scala的Enumeration实现中添加一个自定义字段,比如label。这个新的字段应该通过该枚举的values进行访问。此外,这个自定义字段应该是各种Enumeration的一部分。

我了解到Stackoverflow上有以下几个问题:

然而,它们都不能解决我的问题:

第一个问题是我能够添加一个自定义字段。然而,我无法通过Enumeration.values返回的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)

注意我是通过其中一个值来访问label的。以下代码不起作用:

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

错误消息如下:error: value label is not a member of MyEnum.Value

显然,MyEnum.MyVal被替换为MyEnum.Val。后者没有定义label,而我的自定义值将提供label字段。

第二个问题是在Enumeration的上下文中似乎只能引入自定义的ValueVal。因此,据我所知,不可能在不同的枚举中使用这样的字段。至少,以下代码不能编译:

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在枚举的上下文中没有定义。

有什么办法解决上述问题吗?

0
0 Comments

问题的出现的原因:

根据问题所提到的第一个问题,似乎缺乏一个可重用的字段,这是最近一个问题所关注的问题。作者提到他会写一个定制的widgets方法来解决这个问题,但是他给出的答案只是引入了一个implicit conversion,看起来似乎很方便。但是为什么这个方法不是标准的解决方案,作者并不清楚。

解决方法:

对于第二个问题,派生的MyVal应该只实现一个trait。

示例代码:

trait Labelled { def label: Option[String] }
object A extends Enumeration { case class AA(label: Option[String]) extends Val with Labelled ; val X = AA(Some("one")) }
object B extends Enumeration { case class BB(label: Option[String]) extends Val with Labelled ; val Y = BB(None) }
val labels = List(A.X, B.Y)
labels: List[Enumeration#Val with Product with Labelled] = List(X, Y)
labels map (_.label)
res0: List[Option[String]] = List(Some(one), None)

0