以下是有效的枚举声明。
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);
}
如果没有,为什么不呢?什么是好的选择?
答案 0 :(得分:34)
Enum
,它们隐式final
。枚举可以实现接口,或者您可以直接在相关的枚举类中声明相关方法。
(我确实看到了你想要的基本概念,这是一个混合;也许Java 8接口在这方面会更有用。)
答案 1 :(得分:8)
在java中,你不能扩展枚举或创建一些抽象的枚举,甚至可以生成枚举。 如果你想在你的枚举上有一些多态扩展点,你可以应用这样的模式。
让我们说你的枚举
public enum SomeEnumClass {
ONE, TWO, THREE;
}
并且您希望某些行为与每个值相关联。但是你不想对每个人进行硬编码,而是希望有能力提供其他任何东西。 所以你应该声明接口
public interface SomeEnumVisitor<P, R> {
R one(P param);
R two(P param);
R three(P param);
}
然后为每个值
添加抽象方法以枚举声明和实现此方法public enum SomeEnumClass {
ONE {
@Override
public <R, P> R accept(SomeEnumVisitor<R, P> visitor, P param) {
return visitor.one(param);
}
}, TWO {
@Override
public <R, P> R accept(SomeEnumVisitor<R, P> visitor, P param) {
return visitor.two(param);
}
}, THREE {
@Override
public <R, P> R accept(SomeEnumVisitor<R, P> visitor, P param) {
return visitor.three(param);
}
};
public abstract <R, P> R accept(SomeEnumVisitor<R, P> visitor, P param);
}
这样您就可以创建访问者实现以扩展您的枚举行为。例如,在您的情况下,您希望将Integer值与每个枚举值相关联。
public class IntValueVisitor implements SomeClassVisitor<Integer, Void> {
@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);
当然,如果在enum中声明所有内容是不合适的,那么这种模式是适用的,例如,如果你在库中有enum声明并想在主应用程序中扩展enum的行为。或者您只是不想结合枚举定义和实现细节。
为了简化此模式实现there is a library that can generate enum and visitor based on annotation,以便您需要在代码中声明所有内容
@AutoEnum(value = {"one", "two", "three"}, name = "SomeEnumClass")
public interface SomeEnumMarker {}
该工具将为您休息。
答案 2 :(得分:4)
如果你真的需要“扩展枚举”,你可以使用pre-Java 1.5 Typesafe Enum Pattern(参见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<Operator> 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<Operator> items() {
return ALL_VALUES;
}
public abstract Double apply(Double firstParam, Double secondParam);
}