본문 바로가기
public void static main()/Book

[Effective Java] 아이템 23

by 햄리뮤 2023. 1. 24.
반응형

4장...에서의 정리는 여기까지....

[책 규칙]

노란색 - 자세히 알아보고싶은 부분

초록색 - 핵심 개념 (블로그 정리시는 검은색으로!)

빨간색 - 무슨말인지 모르겠는 부분

[아이템 23] 태그 달린 클래스보다는 클래스 계층 구조를 활용하라

태그?

  • 해당 클래스가 어떠한 타입인지에 대한 정보를 담고있는 맴버 변수를 의미한다!
  • 단점 
    • 쓸데없는 코드들이 많다.
      • 태그에 대한 선언이 필요하기 때문에 열거형 타입 선언, 태그 필드, switch 문 등 쓸데 없는 코드들이 많아진다. 태그에 따른 메서드의 행동이 달라져야 하기 때문에 switch 문이 많아져 가독성이 떨어진다.
    • 메모리를 많이 사용한다.
      • 다른 행동을 위한 코드도 정의되기 때문에 메모리도 많이 사용하게 된다.
    • 불필요한 초기화가 필요하다.
      • 필드를 final로 선언하려면 해당 태그에서 사용되지 않는 필드를 위해서 생성자에서 불필요한 초기화가 필요해진다. 생성자가 태그 필드를 설정하고 해당 태그에 쓰이는 데이터 필드를 초기화하는데 컴파일러가 도와줄 수 있는 부분이 별로 없다. 엉뚱한 필드를 초기화해도 런타임에야 문제가 드러난다.
    • 새로운 코드(행동)를 추가하려면 태그를 추가해야한다.
      • 새로운 태그가 추가될 때마다 모든 switch 문에 새로운 태그에 대한 행동을 처리하는 코드를 추가해야 한다. 따라서 새로운 행동에 대한 switch 문이 하나라도 빼먹고 작성되면, 런타임 에러가 터진다.

태그 달린 클래스는 읽기 어렵기만 하고 오류를 내기 쉬운 비효율적인 클래스이다!

 

태그 달린 클래스를 클래스 계층 구조로 변환 하자!

변경 전

// 태그 달린 클래스
class Figure {
    enum Shape {RECTANGLE, CIRCLE};

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

    // 태그가 RECTANGLE일 때만 사용되는 필드들
    double length;
    double width;

    // 태그가 CIRCLE일 때만 사용되는 필드들
    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);
        }
    }

 

변경 후

abstract class Figure {
	abstract double area();
}

class Circle extends Figure {
	final double = radius;
    
    Circle(double radius) {
    	this.radius = radius;
     }
     
     @Override
     double area() {
     	return Math.PI * (radius * radius);
     }
}

class Rectangle extends Figure {
	final double length;
    final double width;
    
    Rectangle(double length, double  width) {
    	this.length = length;
        this.width = width;
    }
    
    @Override
    double area() {
    	return length * width;
    }
}

위와 같이 변경하면 컴파일 시에 형 검사(type checking)를 하기 용이해진다. 이제 컴파일러의 도움을 받을 수 있게 된 것이다. 또한, 각 구체 클래스의 멤버 변수는 final로 선언할 수 있게 된다.

 

핵심 정리
태그 달린 클래스를 써야 하는 상황은 거의 없다. 새로운 클래스를 작성하는 데 태그 필드가 등장한다면 태그를 없애고 계층 구조로 대체하는 방법을 생각해보자. 기존 클래스가 태그 필드를 사욯하고 있다면 계층 구조로 리팩터링하는 걸 고민해보자.

 

 

 

https://jjingho.tistory.com/66

 

[이펙티브 자바] Item23- 태그 달린 클래스보다는 클래스 계층구조를 활용하라

두 가지 이상의 의미를 표현할 수 있으며, 그중 현재 표현하는 의미를 태그 값으로 알려주는 클래스를 태그 달린 클래스라고 한다. 태그란? 클래스가 어떠한 타입인지에 대한 정보를 담고 있는

jjingho.tistory.com

** 그냥 하루하루 개인 공부한 것을 끄적 거리는 공간입니다.

이곳 저곳에서 구글링한 것과 강의 들은 내용이 정리가 되었습니다.

그림들은 그림밑에 출처표시를 해놓았습니다.

문제가 될시 말씀해주시면 해당 부분은 삭제 하도록하겠습니다. **

반응형

댓글