열거 타입은 보통은 확장에 적합하지 않다.
확장할 수 있는 열거타입이 필요할 때도 있는데 연산 코드가 그 예시다. 사용자 확장 연산을 추가할 수 있도록 열어주는 것이다.
열거 타입이 임의의 인터페이스를 구현하면 된다.
인터페이스를 이용해 확장 가능 열거 타입을 흉내냈다.
public interface Operation {
double apply(double x, double y);
}
public enum BasicOperation implements Operationn {
PLUS("+") {
public double apply(double x, double y) { return x + y; }
},
MINUS("-") {
public double apply(double x, double y) { return x - y; }
},
TIMES("*") {
public double apply(double x, double y) { return x * y; }
},
DIVIDE("/") {
public 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;
}
}
Operation
은 확장할 수 있고, 이 렇게 하면 Operation
을 구현한 또 다른 열거타입을 정희해 대체할 수 있다.
public enum ExtendedOperation implements Operation {
EXP("^") {
public double apply(double x, double y) {
return Math.pow(x, y);
}
},
REMAINDER("%") {
public double apply(double x, double y) {
return x % y;
}
};
private final String symbol;
...
}
inteface를 구현하는 여러 enum들에 접근할 수 있다.
public static void main(String[] args) {
double x = 10;
double y = 2;
test(Arrays.asList(ExtendedOperation.values()), x, y);
}
public static void test(Collection<? extends Operation> opSet, double x, double y) {
for (Operation op : opSet) {
System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y));
}
}
단점은 같은 interface를 implements하는 구현체 enum끼리는 상속이 불가능하다.
공통 부분이 많지 않다면 같은 interface내에서 디폴트 메서드로 구현하고, 공통 부분이 많다면 별도의 도우미 클래스나 정적 도우미 메서드로 분리하자.