연산 코드(operation code)
API가 제공하는 기본 연산 외에 사용자 확장 연산을 추가할 수 있도록 열어줘야 할 때 사용
public interface Operation {
double apply(double x, double y);
}
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;
}
}
인터페이스인 Operation
은 확장할 수 있고, 이 인터페이스를 연산의 타입으로 사용할 수 있음BasicOperation
을 대체할 수 있음타입 수준으로 다형성을 적용할 수 있음
다음과 같이 하나의 메서드로 Operation 하위 타입 모두를 사용할 수 있음
public static void main(String[] args) {
double x = 1.5;
double y = 3.0;
System.out.println("--지구--");
test(EarthOperation.class, x, y);
System.out.println("--화성--");
test(MarsOperation.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));
}
}
한정적 와일드 카드를 이용한 방법
public static void main(String[] args) {
double x = 1.5;
double y = 3.0;
System.out.println("--지구--");
test(EnumSet.allOf(EarthOperation.class), x, y);
System.out.println("--화성--");
test(EnumSet.allOf(MarsOperation.class), x, y);
System.out.println("--지구의 더하기와 화성의 더하기--");
test(Set.of(BasicOperation.PLUS, MarsOperation.MARS_PLUS), x, y);
}
private 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));
}
}
Operation 을 구현한 다른 타입의 enum 상수들을 조합해서 인자로 보낼 수 있음