규칙20. 태그달린 클래스 대신 클래스 계층을 활용하라.

두 가지 이상의 기능을 가지고 있으며, 그 중 어떤 기능을 제공하는지 표시하는 태그가 달린 클래스를 만날 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Figure {
enum Shape { RECTANGLE, CIRCLR };

// 어떤 모양인지 나타내는 태그 필드.
final Shape shape;

//사각형일때만 생성되는 필드
double length;
double width;

//원일때만 사용되는 필드
double radius;

double area(){
...
}

...
}

위의 클래스는 원을 표현할 수도 있고 사각형을 표현할 수 도 있다.

위 처럼 태그달린 클래스는 다양한 문제가 있다.enum선언, 태그필드, switch문 등의 상투적 코드가 반복되는 클래스가 만들어지며, 서로 다른 기능을 위한 코드가 한 클래스가 모여있어 가독성도 떨어진다. 또한 객체를 만들때 불필요한 필드도 함께 생성되어 메모리 요구량도 늘어난다. final을 초기화 하기 위한 상투적인 코드도 늘어나기도 한다. 마지막으로 그 객체가 무슨 기능을 제공하는지 알 수 없다.
한줄로 정리하자면 태그기반(tagged class) 클래스는 너저분하고 오류발생가능성이 높고 비 효율적이다.

태그기반 클래스 대신 하위 자료형 정의(subtyping)를 사용하자.

  • 다양한 기능의 객체들을 하나로 표현하기 위해 태그달린 클래스 대신 하위 자료형 정의(subtyping)를 사용하자.
  • 태그 기반 클래스를 클래스 계층으로 변환하려면 먼저 태그 값에 따라 달리 동작하는 메서드를 추상 메서드로 선언하는 추상클래스를 정의해야 한다. 그리고 추상 클래스를 클래스 계층 맨꼭대기에 둔다.
  • 그리고 태그 값에 좌우되지 않는 메서드는 전부 그 클래스에 넣는다.
  • 모든 기능에 공통되는 데이터 필드도 전부 그 클래스에 넣는다.
  • 태그 기반 클래스가 제공하던 각각의 기능을 방금 만든 최상위 클래스의 객체 생성 가능 하위클래스로 정의한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
abstract class Figure {
abstract double area();
}

class Circle extends Figure {
final double radius;

double area(){
...
}
}

class Rectangle extends Figure {
final double length;
final double width;

double area(){
...
}

}

위 코드가 하위자료형 정의한것이다. 단순하고명료하며 원래 클래스에 있던 단점들이 없다. 또한 최상위 클래스의 소스코드를 보지 않고도 독립적으로 일하면서 협력할 수 있게 된다. 기능마다 별도의 자료형이 있기 때문에 변수가 가진 기능이 무엇인지 명시적으로 표현 가능하며, 특정한 기능을 갖춘 자료형의 객체만이 변수나 인자에 할당되도록 할 수 있다.

요약하자면 태그 기반 클래스 사용은 피하고 클래스 안에 태그 필드를 명시적으로 두고 싶다면 클래스 계층을 통해 태그를 제거할 방법이 없는지 생각해 봐라.

/

Share