在您的用例(属性编辑器)中,我认为最好的解决方案是依赖 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)
万岁?不,因为从Value
to的转换ValueWithEnum
仅在访问时完成red.enum
,而不是在Colors
枚举实例化时完成。换句话说,在调用enum
编译器时需要知道枚举的确切静态类型(编译器必须静态知道 red 的类型是Colors.Value
,而不仅仅是Enumeration# Value
)。而在你提到的用例(属性编辑器)中,你只能依靠java反射(我已经假设你不会使用scala反射)来获取枚举值的类型,而java反射只会给你Enumeration#Val
( extends Enumeration#Value
) 作为 的类型Colors.Red
。所以基本上你被困在这里。你最好的选择肯定是首先使用 scala 反射。