声明枚举而不指定值,类似于抽象

时间:2014-05-01 21:01:18

标签: java enums abstract

我有一个抽象类(或接口)。在这个类中,我想定义一个枚举,以强制扩展这个抽象类(或实现这个接口)的类声明一个具有相同名称的枚举。

abstract class Operator {
    public abstract enum Symbol;
    public Symbol value;
}

class Binary extends Operator {
    public enum Symbol {
        pls,
        min,
        mul,
        div,
        //...
    }
}
class Unary extends Operator {
    public enum Symbol {
        sin,
        cos,
        tan,
        cot,
        //...
    }
}

假设我无法知道子类枚举的值。我希望每个扩展类都有一个带有该名称及其值的枚举。我想使用枚举(特别是因为它很容易切换枚举)

3 个答案:

答案 0 :(得分:2)

没有办法做这件事,而且,即使它是,你将如何调用子类的实现?我的意思是,只有方法调用可以是虚拟,即在运行时调度。类型不能,所以不用反射作弊(无论如何都抛弃任何类型的安全性,这样你甚至不需要子类),你将无法调用重写的类型(事实上) ,类型不能被覆盖)。

也许你仍然可以通过使用作文来实现你的目标:

public abstract class Operator<T extends Enum<T>> {
  public final Class<T> symbol;
  public Operator(Class<T> symbol) { this.symbol = symbol; }
}

public enum BinarySymbol { PLS, MIN, MUL, DIV }

public class Binary extends Operator<BinarySymbol> {
  public Binary(Object operand1, Object operand2, BinarySymbol symbol) {
    super(symbol);
  }
}

您的基类Operator可以通过Class.getEnumConstants()

通过反射动态读取枚举值

答案 1 :(得分:-1)

您无法在编译时强制执行此操作。一种方法是在运行时使用反射来查看该类是否已正确实现。我不建议这样做,但这是可能的。

答案 2 :(得分:-1)

你可以做的是拥有实现通用接口的枚举,然后利用这些接口:

public interface YourEnumInterface<E extends Enum<E> & YourEnumInterface<E>> {

    //methods that your enum should be implementing

}

接口通用声明的扩展是为了保证它只由实现接口的枚举调用

然后你必须指定的任何枚举都可以这样实现它:

public enum MyEnum implements YourEnumInterface<MyEnum> {

    // enum constants
    TEST_VALUE;

    // implementation of interface methods

}

从那里开始,您只需使用YourEnumInterface作为对象,就可以为它们传递枚举值:

public void doSomething(YourEnumInterface enm) {
    //work with enm
}

//Elsewheres...
doSomething(MyEnum.TEST_VALUE);

应该注意的是,一旦你将枚举降低到接口本身,你将无法改变你正在使用的常量(没有强制转换,这可能是不安全的)。这应该或多或少地用于将事物传递到只与值一起使用的目的地(如配置枚举或字符串内部化等)

因此,与强制子类实现它相关:

public class YourSuperClass {
    public abstract YourEnumInterface symbol;
}

可运行的示例

public class EnumMagic {

    public static void main(String[] args) {
        YourSubClass clazz = new YourSubClass();
        //prints the default value
        System.out.println(clazz.getEnum().getValue());
        //gets the value of a specified enum constant
        System.out.println(clazz.getEnum().SECOND_TEST.getValue());
    }

}

abstract class YourSuperClass {

    protected YourEnumInterface symbol;

    public abstract YourEnumInterface getEnum();

}

interface YourEnumInterface<E extends Enum<E> & YourEnumInterface<E>> {

    public int getValue();

}

class YourSubClass extends YourSuperClass {

    public enum MyEnum implements YourEnumInterface<MyEnum> {

        TEST_VALUE(1),
        SECOND_TEST(2);

        private final int val;

        private MyEnum(int example) {
            this.val = example;
        }

        public int getValue() {
            return this.val;
        }

    }

    public YourSubClass() {
        this.symbol = MyEnum.TEST_VALUE;
    }

    public MyEnum getEnum() {
        return MyEnum.TEST_VALUE;
    }

}

这个程序的输出是:

1
2

你可以通过getEnum简单地让类'指定枚举常量,它们将返回它们自己的内部枚举。

然而,一旦下传到超级类型,例如YourSuperClass intc = clazz;,那么你将失去指定枚举本身的能力。根据您存储实例的方式,将确定是否需要更改。