在您的用例(属性编辑器)中,我认为最好的解决方案是依赖 scala 2.10 中可用的 scala 反射。给定一个类的TypeTag,您可以获得其所有成员的完整类型(无需擦除)以及它们的值,并从中填充您的属性编辑器。对于枚举,使用TypeTag以下方法获取它们的值:
使用 Scala 2.10 反射如何列出枚举的值?
现在,也许你不想或不能使用 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 ...它被声明为 final,Enumeration所以没有办法覆盖它。(再次注意,分叉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)
万岁?不,因为从Valueto的转换ValueWithEnum仅在访问时完成red.enum,而不是在Colors枚举实例化时完成。换句话说,在调用enum编译器时需要知道枚举的确切静态类型(编译器必须静态知道 red 的类型是Colors.Value,而不仅仅是Enumeration# Value)。而在你提到的用例(属性编辑器)中,你只能依靠java反射(我已经假设你不会使用scala反射)来获取枚举值的类型,而java反射只会给你Enumeration#Val( extends Enumeration#Value) 作为 的类型Colors.Red。所以基本上你被困在这里。你最好的选择肯定是首先使用 scala 反射。