본문 바로가기

STUDY/이펙티브자바

4-9) 태그 달린 클래스보다는 클래스 계층구조를 활용하라

태그달린 클래스

 

class Figure {
    enum Shape { RECTANGLE, CIRCLE };

    // 도형의 형태를 나타내는 태그 필드
    final Shape shape;

    double length;
    double width;

    double radius;

    Figure(double radius) {
        shape = Shape.CIRCLE;
        this.radius = radius;
    }

    Figure(double length, double width) {
        shape = Shape.RECTANGLE;
        this.length = length;
        this.width = width;
    }

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

클래스의 유형을 나타내는 태그 필드를 가지고 있는 클래스를 태그달린 클래스라고 한다. 위의 예제를 보면 Figure라는 도형 클래스가 있다. 그리고 Figure 클래스는 shape에 RECTANGLE, CIRCLE 값을 가지면서 도형이 사각형인지 원인지를 나타내고 있다. 도형 클래스의 사각형, 원 유형을 태그로 나타내는 태그 클래스인 것이다.

 

태그 클래스에는 단점이 많다. 1) 먼저 열거 타입 선언, 태그 필드, switch문 등 쓸데 없는 코드가 많다. 2) 여러 유형의 코드가 한 클래스에 들어있어서 가독성이 나쁘다. 3) 여러 유형의 데이터를 가지고 있어야 하기 때문에 메모리가 낭비된다. 4) 생성자가 많아지고 불필요한 추가 동작이 추가된다. 5) 유형을 추가하려면 기존 코드 수정이 필요하다. 6) 인스턴스 타입으로는 유형을 알수 없고 태그 필드까지 확인해야 한다.

 

태그클래스는 장황하고, 오류가 발생하기 쉽고, 비효율적이다.

 

 


상속을 활용한 계층구조

 

// Figure.java
abstract class Figure {
    public abstract double area();
}

// Rectangle.java
class Rectangle extends Figure {
    private final double length;
    private final double width;

    public Rectangle(double length, double width) {
        this.length = length;
        this.width  = width;
    }
    
    @Override
    public double area() { return length * width; }
}

// Circle.java
class Circle extends Figure {
    private final double radius;

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

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

태그를 사용하여 유형을 표현하는 대신 상속을 사용하여 유형을 나타내도록 하면 태그클래스의 단점들이 모두 해결된다. 모든 유형들의 공통 내용을 상위 추상클래스로 보내고, 유형별 상세 내용을 각자의 유형이 가지도록 구현하면 된다. 그 덕분에 1) 각 클래스에는 필요한 코드만 존재한다. 2) 가독성이 좋다. 3) 메모리낭비가 없다. 4) 생성자가 깔끔해진다. 5) 유연하게 새로운 유형 추가가 가능하다. 6) 인스턴스의 타입만으로 유형을 알 수 있다.

728x90