在您的用例(属性编辑器)中,我认为最好的解决方案是依赖 scala 2.10 中可用的 scala 反射。给定一个类的TypeTag,您可以获得其所有成员的完整类型(无需擦除)以及它们的值,并从中填充您的属性编辑器。对于枚举,使用TypeTag 使用以下方法获取它们的值:
Using Scala 2.10 reflection how can I list the values of Enumeration?
现在,也许你不想或不能使用 scala 反射,从现在开始我会假设是这种情况。如果这是真的,那么你正在打开一整罐蠕虫:)
TL;DR:这是不可能使用标准的Enumeration,所以你可能不得不明确地包装枚举值,如 Ptharien 的 Flame 的答案所示(或滚动你自己的 Enumeration )。下面我详细介绍我的所有尝试,请多多包涵。
不幸的是,出于某种未知的原因(尽管我怀疑这与序列化问题有关),Enumeration.Value 没有指向其Enumeration 实例的字段。鉴于Enumeration 是如何实现的,这将是微不足道的实现,但我们当然没有发言权,除了分叉枚举和修改我们的版本(这实际上是我为此目的所做的,加上对序列化和添加适当的支持)反思——但我离题了)。
如果我们不能修改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 ... 在Enumeration 中被声明为final,所以没有办法覆盖它。 (再次注意,分叉Enumeration 可以规避这一点。实际上,为什么不这样做,因为我们已经走上了使用自定义枚举的道路。我会让你判断)。
所以这是另一种看法:
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 时,编译器需要知道枚举的确切静态类型(编译器必须静态知道red 的类型是Colors.Value,而不仅仅是Enumeration# Value)。而在你提到的用例(属性编辑器)中,你只能依靠java反射(我已经假设你不会使用scala反射)来获取枚举值的类型,而java反射只会给你@987654345 @(扩展 Enumeration#Value)作为 Colors.Red 的类型。所以基本上你被困在这里。
最好的选择肯定是首先使用 scala 反射。