Item 38. Extended Enum
확장할 수 있는 열거 타입이 필요하면 인터페이스를 사용하라.
열거 타입에 단점 중 하나는 확장이 불가능하다는 것이다. 열거 타입을 확장하는 방법은 없지만, 인터페이스를 사용하면 비슷한 효과를 낼 수 있다. 대부분의 상황에서는 열거 타입을 확장하는 것이 좋지 않지만, 확장할 수 있는 열거 타입이 필요하다면 인터페이스를 사용하자. 대표적인 예로 연산 코드를 나타내는 열거 타입이 있다.
interface Operation {
double apply(double x, double y);
}
enum BasicOperation implements Operation {
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;
}
}
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;
ExtendedOperation(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return symbol;
}
}
인터페이스의 Operation을 확장하여, 이 인터페이스를 연산의 타입으로 사용한 열거 타입 BasicOperation을 정의했다. 이렇게 하면 다음과 같은 이점을 얻을 수 있다.
apply 메서드가 인터페이스에 선언되어 있어 별도로 추상 메서드를 선언할 필요가 없음
인터페이스를 구현한 열거 타입을 만들어 연산 코드를 쉽게 추가 및 대체 가능
아래 코드는 인터페이스를 확장한 확장된 연산 코드를 적용한 예시이다.
import java.util.Collections;
class Main {
public static void main(String[] args) {
double x = 2.0;
double y = 4.0;
test1(BasicOperation.class, x, y);
test1(ExtendedOperation.class, x, y);
test2(Arrays.asList(ExtendedOperation.values()), x, y);
}
/**
* @param opEnumType: class 리터럴을 넘겨 확장된 열거 타입의 Class 객체를 넘겨 확장된 연산들을 알려줌
* @param x
* @param y
* @param <T>: T extends Enum<T> & Operation -> T는 열거 타입이면서 Operation 인터페이스를 구현한 타입
*/
private static <T extends Enum<T> & Operation> void test(Class<T> opEnumType, double x, double y) {
for (Operation op : opEnumType.getEnumConstants()) {
System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y));
}
}
/**
* @param opSet: 한정적 와일드 카드 타입을 사용하여, 확장된 열거 타입의 인스턴스 집합을 받음
* @param x
* @param y
*/
private static void test2(Collections<? 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));
}
}
}
Last updated
Was this helpful?