我可以在Java中创建一个抽象枚举吗?

以下是有效的枚举声明。

public enum SomeEnumClass { ONE(1), TWO(2), THREE(3); private int someInt; public SomeEnumClass(int someInt) { this.someInt = someInt; } } 

但是我可以用枚举类型覆盖抽象类吗?

SomeEnumClass.java

 public abstract enum SomeEnumClass { private int someInt; public SomeEnumClass(int someInt) { this.someInt = someInt; } } 

OverridingEnumClass.java

 public enum OverridingEnumClass extends SomeEnumClass { ONE(1), TWO(2), THREE(3); } 

如果没有,为什么不呢? 什么是好的选择?

不,你不能; 枚举类型都扩展了Enum ,它们是隐式final 。 枚举可以实现接口,也可以直接在有问题的枚举类中声明相关方法。

(我确实看到了你想要的基本概念,这是一个混合;也许Java 8接口在这方面会更有用。)

如果你真的需要“扩展枚举”,你可以使用实际使用类的Java-Type 1.5 Typesafe枚举模式(参见http://www.javacamp.org/designPattern/enum.html的底部),不是枚举。 您失去了使用EnumSet和“枚举”的能力,并且您丢失了一些自动生成的方法,例如items(),但您可以覆盖方法。

一个例子:

 // Typesafe enum pattern public static abstract class Operator { public static final Operator ADD = new Operator("+") { @Override public Double apply(Double firstParam, Double secondParam) { return firstParam + secondParam; } }; public static final Operator SUB = new Operator("-") { @Override public Double apply(Double firstParam, Double secondParam) { return firstParam - secondParam; } }; public static final Operator MUL = new Operator("*") { @Override public Double apply(Double firstParam, Double secondParam) { return firstParam * secondParam; } }; public static final Operator DIV = new Operator("/") { @Override public Double apply(Double firstParam, Double secondParam) { return firstParam / secondParam; } }; private static final Operator[] _ALL_VALUES = {ADD, SUB, MUL, DIV}; private static final List ALL_VALUES = Collections.unmodifiableList(Arrays.asList(_ALL_VALUES)); private final String operation; private Operator(String c) { operation = c; } // Factory method pattern public static Operator fromToken(String operation) { for (Operator o : Operator.items()) if (o.operation.equals(operation)) return o; return null; } public Iterable items() { return ALL_VALUES; } public abstract Double apply(Double firstParam, Double secondParam); } 

在java中,你不能扩展枚举或创建一些抽象枚举甚至是枚举枚举。 如果你想在你的枚举上有一些多态扩展点,你可以应用这样的模式。

让我们说你的枚举

 public enum SomeEnumClass { ONE, TWO, THREE; } 

并且您希望有一些与每个值相关联的行为。 但是你不想对每个硬编码,而是希望有能力提供任何其他的。 所以你应该声明接口

 public interface SomeEnumVisitor { R one(P param); R two(P param); R three(P param); } 

然后为每个值添加抽象方法以枚举声明和实现此方法

 public enum SomeEnumClass { ONE { @Override public  R accept(SomeEnumVisitor visitor, P param) { return visitor.one(param); } }, TWO { @Override public  R accept(SomeEnumVisitor visitor, P param) { return visitor.two(param); } }, THREE { @Override public  R accept(SomeEnumVisitor visitor, P param) { return visitor.three(param); } }; public abstract  R accept(SomeEnumVisitor visitor, P param); } 

这样您就可以创建访问者实现以扩展您的枚举行为。 例如,在您的情况下,您希望将Integer值与每个枚举值相关联。

 public class IntValueVisitor implements SomeClassVisitor { @Override public Integer one(Void param){ return 1; } @Override public Integer two(Void param){ return 2; } @Override public Integer three(Void param){ return 3; } } 

最后在您需要的地方使用此访问者

 SomeClassEnum something = getAnyValue(); // this expression will return your particular int value associated with particular enum. int intValue = something.accept(new IntValueVisitor(), null); 

当然,如果不适合在枚举内声明所有内容,这种模式适用,例如,如果你在库中有枚举声明并想在主应用程序中扩展枚举行为。 或者您只是不想结合枚举定义和实现细节。

为了简化这种模式实现, 有一个库可以根据注释生成枚举和访问者,因此您需要在代码中声明所有内容

 @AutoEnum(value = {"one", "two", "three"}, name = "SomeEnumClass") public interface SomeEnumMarker {} 

该工具将为您rest。