태그 달린 클래스에는 단점이 한가득하다.
우선 열거 타입 선언, 태그 필드, switch 문 등 쓸데없는 코드가 많다.
다른 의미를 위한 코드도 언제나 함께하니 메모리도 많이 사용한다.
필드를 final로 선언하려면 해당 의미에 쓰이지 않는 필드들까지 생성자에서 초기화해야 한다.
그리고 컴파일러가 도와줄 수 있는 것이 별로 없다.
런타임에야 문제가 드러날 뿐이다.
또 다른 의미를 추가하려면 코드를 수정해야 한다.
마지막으로, 인스턴스의 타입만으로는 현재 나타내는 의미를 알 길이 전혀 없다는 것이다.
그렇기에 태그 달린 클래스보다는 클래스 계층구조를 활용하는 편이 더 좋다.
태그 달린 클래스를 클래스 계층구조로 바꾸는 법을 알아보자.
우선 먼저 계층구조의 루트가 될 추상 클래스를 정의하고, 태그값에 따라 동작이 달라지는 메서드들을 루트 클래스의 추상 메서드로 선언한다.
그런 다음 태그값에 상관없이 동작이 일정한 메서드들을 루트 클래스에 일반 메서드로 추가한다.
모든 하위 클래스에서 공통으로 사용하는 데이터 필드들도 전부 루트 클래스로 올린다.
그리고 루트 클래스를 확장한 구체 클래스를 의미별로 하나씩 정의한다.
클래스 계층구조는 타입 사이의 자연스러운 계층 관계를 반영할 수 있어서 유연성은 물론 컴파일 타임 타입 검사 능력도 높여준다는 장점이 있다.