✍️ 서론
논리적으로 연관된 상수를 정의할 때 사용하는 자료형 enum.
enum은 심볼릭하게 그 자체로도 의미를 가지지만 필요에 따라 필드를 추가하거나 메서드를 추상화해서 enum이 책임질 수 있는 코드를 구현할 수 있다.
🍊 simple enum
enum의 가장 단순한 사용법으로 보통 상태 값이나, 분기를 위한 플래그로 사용된다.
public enum Operator {
PLUS,
MINUS,
MULTIPLY,
DIVIDE;
}
public class Calculator {
public double calculate(double a, double b, Operator op) {
if (op == Operator.PLUS) {
return a + b;
} else if (op == Operator.MINUS) {
return a - b;
} else if (op == Operator.MULTIPLY) {
return a * b;
} else if (op == Operator.DIVIDE) {
return a / b;
}
throw new IllegalArgumentException("Illegal Operator : " + op);
}
}
class CalculatorTest {
@Test
public void test_calculate() {
Calculator calculator = new Calculator();
double res = calculator.calculate(1.0, 2.0, Operator.PLUS);
assertEquals(res, 3.0);
}
}
🌱 field
enum은 필드를 가질 수 있다. 필드에 함수형 인터페이스를 선언하고 Java 8에 추가된 람다 표현식을 활용하면 코드가 간결해지고 계산이란 행위를 enum에서 책임질 수 있게 된다.
@AllArgsConstructor
public enum Calculator {
PLUS((a, b) -> a + b),
MINUS((a, b) -> a - b),
MULTIPLY((a, b) -> a * b),
DIVIDE((a, b) -> a / b);
private BinaryOperator<Double> binaryOperator;
public double calculate(double a, double b) {
return binaryOperator.apply(a, b);
}
}
class CalculatorTest {
@Test
public void test_calculator() {
Calculator calculator = Calculator.PLUS;
double res = calculator.calculate(1.0, 2.0);
assertEquals(res, 3.0);
}
}
🍃 abstract method
enum에 추상 메서드를 추가해서 상수가 가진 의미에 따라 메서드를 구현하도록 유도할 수 있다.
public enum Calculator {
PLUS {
@Override
public double calculate(double a, double b) {
return a + b;
}
},
MINUS {
@Override
public double calculate(double a, double b) {
return a - b;
}
},
MULTIPLY {
@Override
public double calculate(double a, double b) {
return a * b;
}
},
DIVIDE {
@Override
public double calculate(double a, double b) {
return a / b;
}
};
public abstract double calculate(double a, double b);
}
class CalculatorTest {
@Test
public void test_calculator() {
Calculator calculator = Calculator.PLUS;
double res = calculator.calculate(1.0, 2.0);
assertEquals(res, 3.0);
}
}
혹은 추상 메서드가 아닌 일반 메서드를 정의하고, 특정 상수에서 재정의 할 수 있다.
public enum Grade {
GOLD,
VIP,
VVIP {
@Override
public double discountRate() {
return 0.2;
}
};
public double discountRate() {
return 0.1;
}
}
class GradeTest {
@Test
public void test_grade() {
assertEquals(Grade.GOLD.discountRate(), 0.1);
assertEquals(Grade.VIP.discountRate(), 0.1);
assertEquals(Grade.VVIP.discountRate(), 0.2);
}
}