Item 34. 확장 가능한 enum을 만들어야 한다면 인터페이스를 이용하라.
public interface Operation{
    double apply(doube x, double y);
}

public enum BasicOperation implements Operation{
    PLUS("+")   {double apply(double x, double y) {return x + y;}},
    MINUS("-")  {double apply(double x, double y) {return x - y;}},
    TIMES("*")  {double apply(double x, double y) {return x * y;}},
    DIVIDE("/") {double apply(double x, double y) {return x / y;}};
    
    private final String symbol;
    
    BasicOperation(String symbol){
        this.symbol = symbol;
    }
    
    @Override
    public String toString(){
        return symbol;
    }
}

BasicOperation은 enum자료형이라 계승할 수 없지만 Operation은 인터페이스라 확장이 가능하다.

public enum ExtendedOperation implements Operation {
    EXP("^") {double apply(double x, double y) {return Math.pow(x,y);}}
    REMAINDER("%") {double apply(double x, double y) {return x % y;}}
    
    private final String symbol;
    
    ExtendedOperation(String symbol){
        this.symbol = symbol;
    }
    
    @Override
    public String toString(){
        return symbol;
    }
}

1. 한정적 자료형 토근(bounded type token)

public static void main(String[] args) {
    double x = Double.parseDouble(args[0]);
    double y = Double.parseDouble(args[1]);
    test(ExtendedOperation.class, x, y);
}

private static <T extends Enum<T> & Operation> void test(Class <T> ops, double x, double y) {
    for (Operation op : ops.getElementConstants()) {
        System.out.printf("%f %s %f = %f%n", x, op, op.apply(x, y));
    }
}

<T extends Enum<T> & Operation>타입 파라미터는 Class<T>객체가 나타내는 자료형이 enum자료힝인 동시에 Operation의 하위 자료형이 되도록 한다.

2. 한정적 와일드 카드 자료형 사용

public static void main(String[] args) {
    double x = Double.parseDouble(args[0]);
    double y = Double.parseDouble(args[1]);
    test(Arrays.asList(ExtendedOperation.values()), x, y);
}

private static void test(Collection< ? extends Operation> ops, double x, double y) {
    for (Operation op : ops) {
        System.out.printf("%f %s %f = %f%n", x, op, op.apply(x, y));
    }
}

결론

계승 가능 enum자료형은 만슬수 없지만, 인터페이스를 만들고 그 인터페이스를 구현하는 기본 enum자료형을 만들면 계승 가능 enum자료형을 흉내 낼수 있다.