这一般处理枚举类斯卡拉(Scala class that handles enumerations

2019-10-17 14:58发布

我想创建一个保存了枚举值的一般类,并允许访问枚举的可能值。 想想例如属性编辑器 - 你需要知道属性的当前价值,还需要能够了解其他值是合法的财产。 与枚举类型不应该事先知道,你应该能够与任何一种枚举的工作。

我首先想到的是这样的:

class EnumerationProperty[T <: Enumeration](value:T)

然而,这并不因为工作的枚举T是不是一个类型,它是一个对象。 我曾尝试其他的变化是:

class EnumerationProperty[T <: Enumeration](value:T.Value)
class EnumerationProperty[T <: Enumeration.Value](value:T)

(我不会去的,为什么这些不工作,因为我怀疑的原因是不是有趣的细节。)

Answer 1:

在你的使用情况(属性编辑器)我认为最好的办法是依靠在斯卡拉2.10可用阶反射。 给定一个类的TypeTag ,你可以得到所有成员以及他们的价值观的全面型(不擦除),并从填充您的属性编辑器。 对于枚举,使用TypeTag使用下面的方法来获得它们的值: 使用Scala的2.10思考如何列出枚举值?


现在,也许你不想或者不能使用Scala的反思,并从现在起,我会想是这样。 如果这是真的,那么你正在打开蠕虫:) TL的整体能; DR:这是不可能的使用标准的Enumeration ,所以你可能要explcitly包裹枚举值,如图Ptharien的火焰的答案(或滚你自主叉Enumeration )。 下面我详细的我所有的努力,请多多包涵。

不幸的是,对于一些未知的原因,我(虽然我怀疑它与序列化问题做), Enumeration.Value没有现场指向其Enumeration的实例。 考虑到如何Enumeration实现,这将是微不足道的实施,当然wehave没有发言权的,短分叉枚举和修改我们的版本(这实际上是我做了这个目的,再加上添加了序列化和反射适当的支持-但我diggress)。

如果我们不能修改Enumeration ,也许我们就可以延期吗? 纵观再次实施,这样的事情似乎工作:

class EnumerationEx extends Enumeration {
  protected class ValEx(i: Int, name: String) extends Val(i, name) {
    @transient val enum: Enumeration = EnumerationEx.this
  }
  override protected def Value(i: Int, name: String): Value = new ValEx(i, name)  
}

object Colors extends EnumerationEx {
  val Red, Green, Blue = Value
}

不利的一面是,这仅适用于枚举明确延长EnumerationEx而不是Enumeration ,但它会比没有好。

不幸的是,这并不编译,只是因为def Value ...被声明为final的Enumeration所以没有方法来覆盖它。 (再次注意,分叉Enumeration将允许circunvent这一点。其实,为什么不这样做,因为我们已经下使用自定义枚举anwyay的道路。我会告诉你判断)。

因此,这里是它的另一个看法:

class EnumerationEx extends Enumeration {
  class ValueWithEnum( inner: Value ) {
    @transient val enum: Enumeration = EnumerationEx.this
  }
  implicit def valueToValue( value: Value ): ValueWithEnum = new ValueWithEnum( value )
}

而事实上按预期工作 。 或者看起来是这样。

scala> object Colors extends EnumerationEx {
     |   val Red, Green, Blue = Value
     | }
defined module Colors

scala> val red = Colors.Red
red: Colors.Value = Red

scala> red.enum.values
res58: Enumeration#ValueSet = Colors.ValueSet(Red, Green, Blue)

万岁? 哦,不,因为从转换Value ,以ValueWithEnum访问时,只是做red.enum ,而不是在实例化时Colors枚举。 换句话说,当调用enum编译器需要知道确切的静态类型枚举(编译器必须静态知道,红色的类型是Colors.Value ,而不是仅仅Enumeration# Value )。 而在使用情况,你提到(属性编辑器),你只能依靠于Java反射(我已经假设你不会使用Scala的反射)来获取枚举值的类型,以及Java反射只会给你Enumeration#Val (其延伸Enumeration#Value )作为类型Colors.Red 。 所以基本上你被困在这儿了。 最好的办法是definitly使用Scala的反射摆在首位。



Answer 2:

对于你的问题的第一部分。 你也可以为这个通用枚举值定义持有者:

case class EnumerationProperty[T <: Enumeration#Value](value:T)

但我不知道怎么弄不明确所有枚举值通过枚举对象。 枚举有values()方法来获取所有值。 和计数#值链接枚举,但私下接触



Answer 3:

class EnumProps[E <: Enumeration](val e: E)(init: e.Value) {...}

然后你可以使用ee.Value实现类。



文章来源: Scala class that handles enumerations generically