Java 是否可以将枚举子类化以强制编译器仅接受某些枚举值?

Java 是否可以将枚举子类化以强制编译器仅接受某些枚举值?,java,javafx,enums,Java,Javafx,Enums,JavaFX声明enum KeyCode,它为公共键盘上的每个键枚举一个代码。我目前正在声明一个函数,该函数只有在给定修改键时才有意义。看起来是这样的: void doStuff(KeyCode c){ if(!c.isModifierKey()) throw new IllegalArgumentException(); ... } 但我认为如果编译器能帮我做这个检查,会更干净。所以,如果我能以某种方式将KeyCode“扩展”到只包含修改键的子集,我的代码就会变得更干净。有人知道怎么

JavaFX声明enum KeyCode,它为公共键盘上的每个键枚举一个代码。我目前正在声明一个函数,该函数只有在给定修改键时才有意义。看起来是这样的:

void doStuff(KeyCode c){
  if(!c.isModifierKey()) throw new IllegalArgumentException();
  ...
}

但我认为如果编译器能帮我做这个检查,会更干净。所以,如果我能以某种方式将KeyCode“扩展”到只包含修改键的子集,我的代码就会变得更干净。有人知道怎么做吗?

您不能在Java中对
enum
进行子类化

您需要定义自己的键码枚举。但我怀疑你在这里不会赢得太多的澄清。您可能希望将
if
命令封装到
assert
方法中,如下所示:

assertModifierKeyCode(KeyCode c) {
   if(!c.isModifierKey()) throw new IllegalArgumentException();
}
那么,您的方法的含义就更简洁了一点:

void doStuff(KeyCode c){
   assertModifierKeyCode(c);
    ...
}
当然,在调用
doStuff
之前,您可以自由地检查keycode约束,然后您可以使用
ModifierCode
enum作为过滤器:

ModifierCode m = ModifierCode.fromKeyCode(c); // could throw Exception
doStuff( m );

...

void doStuff( ModifierCode m ) {
   switch ( m ) {
   case ...
}
要使
KeyCode
仍然可用,您可以构造嵌入
KeyCode
ModifierCode

public enum ModifierCode {

   LSHIFT(KeyCode.LeftShift),
   RSHIFT(KeyCode.RightSHift)  // bear with me, I dont have KeyCode enum in memory
   ; 

   final private KeyCode keyCode;

   private ModifierCode(KeyCode c) {
       this.keyCode = c;
   }

   public KeyCode getKeyCode() {  // maybe asKeyCode() would also be a nifty name :-)
        return keyCode;
   }

   public static ModifierCode fromKeyCode(KeyCode c) {
       for(ModifierCode m : values() ) {
            if( m.keyCode == c ) {
                return m;
            }
       }
       throw IllegalArgumentException("No MOdifierCode with that KeyCode!");
   }
}

我认为这样的事情是不可能的。我最接近的设计建议是确保枚举实现了一个接口,然后将其拆分为两个枚举,一个带有修改键的值,另一个不带修改键。现有方法将采用接口,而不是枚举类。您应该尝试编程到接口,而不是实现


我猜执行运行时检查是最好的解决方案。

当然,一个问题是编译器是否可以为您执行此检查。是否有人传入任意密钥码?您是否只需要使用相同的检查来包装此消息,然后将其转换为假设的子枚举?如果是这样,那就没有好处了。(但不,我不认为这样做是可能的。)我以前考虑过你的上一个建议,但问题是如果我这样做,我就不能再将密钥代码传递给任何javaFX函数了。这不是我所希望的,但这可能是我能做的最好的了。非常感谢你。我真的不明白为什么按我所说的方式扩展枚举是不可能的。你可以在这里找到一些我以前见过的高评价的解释,但该线程中的问题是扩展枚举是否可以添加值。我明白为什么这不是个好主意。但是创建一个子集对我来说似乎很好。你的解决方案只有在你控制了
enum
之后才能起作用,这样你才能将它拆分。不幸的是,
enum
KeyCode
是JDK的一部分,因此在实际应用中是不可更改的。