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

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

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

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

특정 타입이 다른 타입을 확장(상속)하게 되면, 확장된 타입의 인스턴스는 기반 타입의 인스턴스로도 취급될 수 있지만, 그 반대는 성립하지 않는다는 뜻입니다.
기반 타입과 확장된 타입들의 원소를 모두 순회할 수 있는 방법이 마땅치 않습니다.
확장성을 높이기 위해서는 여러 가지 고려해야 할 부분이 있습니다.
그러나 연산 코드(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개의 댓글