스터디/이펙티브 자바

[Effective Java] Item23.태그달린 클래스보다는 클래스 계층구조 활용

📝 작성 : 2022.06.04  ⏱ 수정 : 
728x90
public class Figure {
    enum Shape { RECTANGLE, CIRCLE }

    //태그 필드 
    final Shape shape;

    //Shape가 RECTANGLE일 때만 사용
    double length;
    double width;

    //Shape가 CIRCLE일 때만 사용
    double radius;

    //RECTANGLE용 생성자
    public Figure(double length, double width) {
        this.shape = Shape.RECTANGLE;
        this.length = length;
        this.width = width;
    }

    //CIRCLE용 생성자
    public Figure(Shape shape, double radius) {
        this.shape = Shape.CIRCLE;
        this.radius = radius;
    }

    double area() {
        switch (shape) {
            case RECTANGLE:
                return length * width;
            case CIRCLE:
                return Math.PI * (radius * radius);
            default:
                throw new AssertionError(shape);
        }
    }
}

위의 클래스는 단점이 많습니다.

  1. 열거 타입 선언, 태그 필드, switch 문 등 쓸데없는 코드가 많습니다.
  2. 여러 구현이 혼합되어 있어서 가독성이 좋지 않습니다.
  3. 다른 의미를 위한 코드도 함께 사용하므로 메모리도 많이 사용합니다.
  4. 필드들을 final로 선언하려면 해당 의미에 쓰이지 않는 필드들까지 초기화해야 합니다.
  5. 엉뚱한 필드를 초기화해도 런타임에야 문제가 드러납니다.
  6. 또 다른 의미를 추가하려면 코드를 수정해야 합니다.
  7. 인스턴스의 타입만으로는 현재 나타내는 의미를 알 수 없습니다.

즉, 태그 달린 클래스는 장황ㅎ하고, 오류를 내기 쉬우며 비효율적입니다.

서브 타이핑

abstract class Figure {
    abstract double area();
}

class Circle extends Figure {
    final double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    double area() {
        return Math.PI * (radius * radius);
    }
}

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

    public Rectangle(double length, double width) {
        this.length = length;
        this.width = width;
    }

    @Override
    double area() {
        return length * width;
    }
}

정리

태그 달린 클래스를 써야 하는 상황은 거의 없습니다.

반응형