도당탕탕
Item38 : 인터페이스를 사용해서 확장성있는 ENUM을 재현하라. 본문
개요
Enum을 확장하고 싶을 때, enum을 상속하면 된다고 생각할 수 있는데 문제가 있다. 왜냐하면 상속된 enum type은 부모 enum type이라고 볼 수 있지만, 부모 enum type은 자식 enum type이라고 볼 수 없기 때문에, 서로 확장 관계로 보기에는 헷갈리기 때문이다.
인터페이스를 사용해서 확장성있는 Enum 구현하기
public interface Operation {
double apply(double x, double y);
}
// BasicOperation.java
public enum BasicOperation implements Operation {
PLUS("+"){
@Override
public double apply(double x, double y) {
return x+y;
}
},
MINUS("-"){
@Override
public double apply(double x, double y) {
return x-y;
}
},
TIMES("*"){
@Override
public double apply(double x, double y) {
return x*y;
}
},
DIVIDE("/"){
@Override
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;
}
}
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;
ExtendedOperation(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return symbol;
}
}
위 방식으로 하면 BasicOperation 타입을 사용하는 모든 곳에서 ExtendedOperation 타입으로 치환해도 무방하다.
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> 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));
}
사소한 단점
하나의 enum이 다른 enum타입을 상속할 수 없다는 단점이 있다. 이를 보완하기 위해서 두 개의 enum에 있는 공통 로직을 인터페이스에 default 함수로 구현할 수 있다.
만약, default 함수에서 정의하기에는 코드량이 많다면 helper 클래스나 static helper 함수를 사용해서 코드 중복을 제거할 수 있다.
정리
확장성있는 enum type을 구현하고 싶다면, 인터페이스를 사용해라. 그리고 이 인터페이스를 상속하는 basic enum 타입을 정의해라. 이렇게 하면 클라이언트는 인터페이스를 상속하여 자신만의 enum을 만들 수 있다. 이렇게 하면 basic enum type이 사용되는 모든 곳에서 해당 enum이 사용가능해진다.
'JAVA' 카테고리의 다른 글
Item 40 : 일관적으로 OVERRIDE 어노테이션을 사용하라. (0) | 2022.12.30 |
---|---|
Item39 : 명명 패턴보다 애너테이션을 사용하라 (0) | 2022.12.30 |
Item37: ordinal 인덱싱 대신 EnumMap을 사용하라 (0) | 2022.12.29 |
Item36 : bit 필드 대신 EnumSet을 사용하라. (0) | 2022.12.28 |
Item35 : ordinal 메서드 대신 인스턴스 필드를 사용하라 (0) | 2022.12.28 |
Comments