我可以在Java中制作一个抽象的枚举吗?

2022-08-31 22:33:47

下面是一个有效的枚举声明。

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;
    }
}

OveroveringEnumClass.java

public enum OverridingEnumClass extends SomeEnumClass {

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

}

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


答案 1

不,你不能;枚举类型都扩展,并且它们是隐式的。枚举可以实现接口,也可以直接在相关枚举类上声明相关方法。Enumfinal

(我确实看到了你想要的基本思想,即mixin;也许Java 8接口在这方面会更有用一些。


答案 2

在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);
}

以便您可以创建用于扩展枚举行为的访问者实现。例如,在您的情况下,您希望将整数值与每个枚举值相关联。

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 中声明所有内容,例如,如果您在库中有枚举声明并希望在主应用程序中扩展枚举的行为,则此模式适用。或者,您只是不想将枚举定义和实现细节耦合在一起。

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

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

该工具将为您完成休息。