ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 아이템 38. 확장할 수 있는 열거 타입이 필요하면 인터페이스를 사용하라
    JAVA/Effective java 2021. 4. 14. 21:26
    • 열거 타입은 거의 모든 상황에서 타입 안전 열거 패턴보다 우수하다.
    • 단 예외가 하나 있는데 타입 안전 열거 패턴은 확장할 수 있으나 열거 타입은 그럴 수 없다는 점이다.
    • 달리 말하면, 타입 안전 열거 패턴은 열거한 값들을 그대로 가져온 다음 값을 더 추가하여 다른 목적으로 쓸 수 있는 반면, 열거 타입은 그렇게 할 수 없다.

     

     

    • 사실 대부분 상황에서 열거 타입을 확장하는 건 좋지 않은 생각이다.
    • 확장한 타입의 원소는 기반 타입의 원소로 취급하지만 그 반대는 성립하지 않는다면 이상하기 때문이다. 
    • 또한 기반 타입과 확장된 타입들의 원소 모두를 순회할 방법도 마땅치 않다.

     

    • 그런데 확장할 수 있는 열거 타입이 어울리는 쓰임이 최소 하나는 있다.
    • 바로 연산 코드인데 연산 코드의 각 원소는 특정 기계가 수행하는 연산을 뜻한다.
    • 이 열거 타입으로 효과를 내는 방법은 열거 타입이 임의의 인터페이스를 구현할 수 있다는 사실이다.

     

    • 연산 코드용 인터페이스를 정의하고 열거 타입이 이 인터페이스를 구현하게 하자.
    • 이때 열거 타입이 그 인터페이스의 표준 구현체 역할을 한다.
    • 다음은 아이템 34의 Operation 타입을 확장할 수 있게 만든 코드다.

    • 열거 타입인 BaseOperation은 확장할 수 없지만 인터페이스인 Operation은 확장할 수 있고, 이 인터페이스를 연산의 타입으로 사용하면 된다.
    • 이렇게 하면 Operation을 구현한 또 다른 열거 타입을 정의해 기본 타입인 BasicOperation을 대체할 수 있다.
    • 예를 들어 앞의 연산 타입을 확장해 지수 연산(EXP)와 나머지 연산(REMAINDER)을 추가해보자.
    • 우리가 할 일은 Operation 인터페이스를 구현한 열거 타입을 작성하는 것뿐이다.

     

    • 새로 작성한 연산은 기존 연산을 쓰던 곳이면 어디든 쓸 수 있다.
    • Operation 인터페이스를 사용하도록 작성되어 있기만 하면 된다.
    • apply가 인터페이스에 선언되어 있으니 열거 타입에 따로 추상 메서드로 선언하지 않아도 된다.

     

     

    • 개별 인스턴스 수준에서 뿐 아니라 타입 수준에서도, 기본 열거 타입 대신 확장된 열거 타입을 넘겨 확장된 열거 타입의 원소 모두를 사용하게 할 수도 있다.
    • 다음 코드는 ExtendOperation의 모든 원소를 테스트하도록 수정한 모습이다.

    • main 메서드는 test 메서드에 ExtendedOperation의 class 리터럴을 넘겨 확장된 연산들이 무엇인지 알려준다.
    • 여기서 class 리터럴은 한정적 타입 토큰 역할을 한다.
    • Class 객체가 열거 타입인 동시에 Operation의 하위 타입이어야 하는데 열거 타입이여야 원소를 순회할 수 있고, operation이어야 원소가 뜻하는 연산을 수행할 수 있기 때문이다.

     

     

    • 두 번째 대안은 Class 객체 대신 한정적 와일드카드 타입인 Collection<? extends Operation>을 넘기는 방법이다.

    • 인터페이스를 이용해 확장 가능한 열거 타입을 흉내 내는 방식에도 한 가지 사소한 문제가 있다.
    • 바로 열거 타입끼리 구현을 상속할 수 없다는 점이다.
    • 아무 상태에도 의존하지 않는 경우에는 디폴트 구현을 이용해 인터페이스에 추가하는 방법이 있다.

     

     

     

     

    핵심 정리


    • 열거 타입 자체는 확장할 수 없지만, 인터페이스와 그 인터페이스를 구현하는 기본 열거 타입을 함께 사용해 같은 효과를 낼 수 있다.
    • 이렇게 하면 클라이언트는 이 인터페이스를 구현해 자신만의 열거 타입을 만들 수 있다.
    • 그리고 API가 인터페이스 기반으로 작성되면 기본 열거 타입의 인스턴스가 쓰이는 모든 곳을 새로 확장한 열거 타입의 인스턴스로 대체해 사용할 수 있다.

     

Designed by Tistory.