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

MC *_*ror 36 java enums

以下是有效的枚举声明.

public enum SomeEnumClass {

    ONE(1), TWO(2), THREE(3);

    private int someInt;

    public SomeEnumClass(int someInt) {
        this.someInt = someInt;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

SomeEnumClass.java

public abstract enum SomeEnumClass {

    private int someInt;

    public SomeEnumClass(int someInt) {
        this.someInt = someInt;
    }
}
Run Code Online (Sandbox Code Playgroud)

OverridingEnumClass.java

public enum OverridingEnumClass extends SomeEnumClass {

    ONE(1), TWO(2), THREE(3);

}
Run Code Online (Sandbox Code Playgroud)

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

chr*_*ke- 37

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

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

  • 啊,幸运的是,`enum`可以实现`接口`.所以我用它作为替代品. (10认同)

rus*_*t0R 9

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

让我们说你的枚举

public enum SomeEnumClass {
    ONE, TWO, THREE;
}
Run Code Online (Sandbox Code Playgroud)

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

public interface SomeEnumVisitor<P, R> {
     R one(P param);
     R two(P param);
     R three(P param);
}
Run Code Online (Sandbox Code Playgroud)

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

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);
}
Run Code Online (Sandbox Code Playgroud)

这样您就可以创建访问者实现以扩展您的枚举行为.例如,在您的情况下,您希望将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;
     }    
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

@AutoEnum(value = {"one", "two", "three"}, name = "SomeEnumClass")
public interface SomeEnumMarker {}
Run Code Online (Sandbox Code Playgroud)

该工具将为您休息.


Mar*_*cin 6

如果您确实需要“扩展枚举”,则可以使用实际使用类的前 Java 1.5 类型安全枚举模式(请参阅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); 

}
Run Code Online (Sandbox Code Playgroud)