확장 가능한 열거타입 사용하기

밀크야살빼자·2024년 3월 18일

타입 안전 열거 패턴은 열거한 값들을 그대로 가져온 다음에는 확장이 불가능한 반면, 열거 타입은 추가적인 값의 확장이 가능합니다. 그러나 열거 타입을 확장하는 것은 일반적으로 권장되지 않습니다.

그 이유는 다음과 같습니다:

특정 타입이 다른 타입을 확장(상속)하게 되면, 확장된 타입의 인스턴스는 기반 타입의 인스턴스로도 취급될 수 있지만, 그 반대는 성립하지 않는다는 뜻입니다.
기반 타입과 확장된 타입들의 원소를 모두 순회할 수 있는 방법이 마땅치 않습니다.
확장성을 높이기 위해서는 여러 가지 고려해야 할 부분이 있습니다.
그러나 연산 코드(operation code 또는 opcode)와 같이 확장 가능한 열거 타입이 적절한 상황도 있습니다. 이 경우, 기본 아이디어는 열거 타입이 임의의 인터페이스를 구현할 수 있다는 점을 이용하는 것입니다.

public interface Operation {
	double apply(double x, double y);
}
public enum BasicOperation implements Operation {
	 PLUS("+") {
        public double apply(double x, double y) {
            return x + y;
        }
    },
    MINUS("-") {
        public double apply(double x, double y) {
            return x - y;
        }
    },
    TIMES("*") {
        public double apply(double x, double y) {
            return x * y;
        }
    },
    DIVIDE("/") {
        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;
    }
}

열거 타입인 BasicOperation은 확장이 불가능하지만, 인터페이스인 Operation은 확장이 가능합니다. 따라서 Operation을 구현한 다른 열거 타입을 정의하여 기본 타입을 사용할 수 있습니다.
이러한 방식으로, Operation 인터페이스를 구현하는 새로운 열거 타입을 정의할 수 있습니다. 이렇게 하면 Operation 인터페이스의 메서드를 구현함으로써 새로운 동작을 추가하고 확장할 수 있으며, 코드의 유연성과 확장성을 높일 수 있습니다.

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;
    }
}

따라서, 클라이언트는 인터페이스를 구현해 자신만의 열거 타입을 만들 수 있으며, 기본 열거 타입의 인스턴스가 쓰이는 모든 곳에서 새로 확장한 열거 타입의 인스턴스로 대체해 사용할 수 있습니다.

장•단점

  • 장점
    • 각 Enum 클래스가 동일한 인터페이스를 구현할 수 있어 코드의 일관성을 유지할 수 있습니다. 이는 유지 보수와 코드 이해에도 도움을 줍니다.
    • 새로운 Enum 클래스를 추가할 때 기존의 인터페이스를 구현하기만 하면 되기 때문에 코드 확장이 용이합니다.(새로운 ResponseCode를 추가하더라도 기존 코드를 수정하지 않고 통일된 방식으로 처리가 가능합니다.)
    • 인터페이스를 통해 다형성을 활용할 수 있습니다.
  • 단점
    • Enum 클래스가 인터페이스를 구현하는 방식은 코드를 이해하기 어려울 수 있습니다.
    • Enum 클래스는 열거형 상수로 제한되어 있어 다른 클래스를 확장하거나 동적으로 변경하는 것이 어려울 수 있습니다.

참고 레퍼런스

  • 이펙티브 자바
profile
기록기록기록기록기록

0개의 댓글