많이들 enum 이 type을 정의 하는 기능으로 알고 계실텐데요. enum은 강력한 다형성을 제공 합니다.
enum에서 다형성을 사용하면 각 열거형 상수마다 동작을 정의할 수 있습니다.
먼저 enum 을 타입 형태로만 사용했을 경우입니다. if 문이 여러개 작성되며 소스가 어려워 집니다.
public enum CalculateType2 {
ADD,
MULTIPLY,
DIVIDE,
}
public class Client2 {
public int someMethod(CalculateCommand2 calculateCommand) {
if ( calculateCommand.getCalculateType() == CalculateType2.ADD ) {
return calculateCommand.getNum1() + calculateCommand.getNum2();
} else if ( calculateCommand.getCalculateType() == CalculateType2.MULTIPLY ) {
return calculateCommand.getNum1() * calculateCommand.getNum2();
} else if ( calculateCommand.getCalculateType() == CalculateType2.DIVIDE ) {
return calculateCommand.getNum1() / calculateCommand.getNum2();
} else {
throw new RuntimeException("Unknown calculate type: " + calculateCommand.getCalculateType());
}
}
}
다형성을 구현하기 위해, 우리는 추상 메서드를 enum에 추가할 것이며 각 열거형 상수에서 이 추상 메더드를 오버라이드할 것입니다.
예를 들어 간단한 계산기를 만들어 볼 것인데요. 이 계산기는 다양한 연산을 지원해야 합니다. 이를 위해 Calculate 라는 enum을 정의하고 각 연산에 해당하는 다형적인 동작을 정의해 보겠습니다.
public enum Calculate1 {
ADD {
@Override
public double apply(double x, double y) {
return x + y;
}
},
MULTIPLY {
@Override
public double apply(double x, double y) {
return x * y;
}
},
DIVIDE {
@Override
public double apply(double x, double y) {
return x / y;
}
};
public abstract double apply(double x, double y);
}
public class CalculateMain1 {
public static void main(String[] args) {
double add = Calculate1.ADD.apply(2, 5);
double multiply = Calculate1.MULTIPLY.apply(2, 5);
System.out.println("add = " + add);
System.out.println("multiply = " + multiply);
}
}
함수형 표현으로 개선해 보겠습니다.
public enum CalculateType {
ADD((num1, num2) -> num1 + num2),
DIVIDE((num1, num2) -> num1 / num2),
MINUS((num1, num2) -> num1 - num2),
MULTIPLY((num1, num2) -> num1 * num2);
private final BiFunction<Integer, Integer, Integer> expression;
CalculateType(BiFunction<Integer, Integer, Integer> calculate) {
this.expression = calculate;
}
public int calculate(int num1, int num2) {
return expression.apply(num1, num2);
}
}
public class CalculateCommand {
private final CalculateType calculateType;
private final int num1;
private final int num2;
public CalculateCommand(CalculateType calculateType, int num1, int num2) {
this.calculateType = calculateType;
this.num1 = num1;
this.num2 = num2;
}
public CalculateType getCalculateType() {
return calculateType;
}
public int getNum1() {
return num1;
}
public int getNum2() {
return num2;
}
}
public class CalculateMain {
public static void main(String[] args) {
CalculateCommand calculateCommand = new CalculateCommand(CalculateType.MULTIPLY, 2, 5);
Client client = new Client();
int i = client.someMethod(calculateCommand);
System.out.println("i = " + i);
}
}