[Java] Enum을 활용하는 방법

 

 

✍️ 서론

논리적으로 연관된 상수를 정의할 때 사용하는 자료형 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);
    }
}