#34 인터페이스를 사용해서 확장 가능한 enum을 만들자
enum은 내부적으로 접근 가능한 생성자가 없기 때문에, 실질적으로 final 클래스입니다.
https://brunch.co.kr/@oemilk/147
따라서 상속(extends)이 불가능하고 확장성 측면에서는 좋지 않습니다.
직접적인 상속이 아닌 인터페이스를 이용하면 확장 가능한 enum을 만들 수 있습니다.
enum에서 구현해야 하는 API들로 구성된 인터페이스를 먼저 구현합니다.
그리고 이 인터페이스를 구현해서 다양한 형태의 enum 클래스들을 만들 수 있습니다.
여기까지는 그저 인터페이스를 구현한 enum 클래스입니다.
앞서 설명했듯이 enum은 상속이 불가능하기 때문에, BasicOperation과 ExtendedOperation enum 클래스의 동작을 이용하려면 아래와 같이 별도의 메서드를 만들어야 합니다.
enum 클래스들이 많아질수록 메서드도 많아져야 하기 때문에 좋지 않습니다.
enum 클래스가 아닌, 인터페이스를 인자로 전달할 수 도 있습니다.
BasicOperation과 ExtendedOperation enum 클래스 모두 Operation 인터페이스를 구현하고 있기 때문에 하나의 메서드를 통해 처리 가능합니다.
이때 바운드 타입 매개변수(bounded type parameter)를 이용할 수 있습니다.
"<T extends Enum<T> & Operation>"은 enum 타입 클래스와 Operation 인터페이스의 서브 타입 요소를 가진다는 의미입니다.
BasicOperation과 ExtendedOperation enum 클래스 둘 다 이 조건에 만족하게 됩니다.
바운드 와일드카드 타입(bounded wildcard type)을 이용할 수 도 있습니다.
"Collection<? extends Operation>"은 Operation 인터페이스의 서브 타입 요소를 가진 Collection을 의미합니다.
BasicOperation과 ExtendedOperation enum 클래스 둘 다 이 조건에 만족하게 됩니다.
타입 매개변수와 바운드 와일드카드 타입의 차이점은 아래와 같습니다.
바운드 타입 매개 변수 : T extends Class & Interface1 & … & InterfaceN (여러 개의 바운드 가능)
바운드 와일드카드 타입 : ? extends SuperType (하나의 바운드 가능)
바운드 와일드카드 타입이 코드상으로 보면 더 깔끔해 보이지만, 하나의 바운드만 가능하기 때문에 확장성 측면에서는 여러 개의 바운드가 가능한 바운드 타입 매개 변수가 더 좋습니다.
확장(상속) 가능한 enum 타입은 만들 수 없지만, 인터페이스를 이용하면 유사하게 만들 수 있습니다.