Item 23 : 태그 달린 클래스보다는 클래스 계층구조를 활용하라
2021. 7. 22. 16:35
책에서 말하는 단점이 많은 형태의 클래스를 먼저 보고 시작하자.
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);
}
}
}
일단 열거타입 선언, 태그 필드 switch문 등 쓸데없는 코드가 너무 많다.
가독성도 좋지 않다.
한 클래스에 짬뽕처럼 중구난방으로 섞여있기 때문에 장황하고 오류를내기 쉽고 비효율적인 코드다.
자바를 어느정도 공부해봤다면 위의 클래스가 깔끔하지 않다는 것 까진 쉽게 알 수 있지만
어떻게 개선해야 하는가? 라고 한다면 고민이 될 수도 있다.
저자는 이런 태그달린 클래스를 계층구조로 바꾸라고 한다.
방법은 다음과 같다.
계층구조의 루트가 될 추상 클래스를 정의하고 태그 값에 따라 동작이 달라지는 메소드들을
루트 클래스의 추상 메소드로 선언한다.
거기에 루트 클래스를 확장한 구체 클래스를 의미별로 하나씩 정의한다.
변환한 코드를 보면서 이해해보자.
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; }
}
Figure 추상 클래스를 만들어 상속받은 형태이다.
이렇게 하면 쓸데 없는 코드도 사라지고 클래스별로 의미가 남기 때문에 가독성도 좋아진다.
이런 예시에서 볼 수 있듯이 태그 달린 클래스를 써야 하는 상황은 거의 없다.
새로운 클래스를 작성하는 데 태그 필드가 등장한다면 태그를 없애고 계층구조로 대체하는 방법을
고민해보는 것이 좋다.
'책 > 이펙티브자바' 카테고리의 다른 글
Item 25 : 탑클래스는 한 파일에 하나만 담으라 (0) | 2021.07.25 |
---|---|
Item 24 : 멤버 클래스는 되도록 static으로 만들라 (0) | 2021.07.24 |
Item 22 : 인터페이스는 타입을 정의하는 용도로만 사용하라 (0) | 2021.07.21 |
Item 21 : 인터페이스는 구현하는 쪽을 설계하라 (0) | 2021.07.20 |
Item 20 : 추상클래스보다는 인터페이스를 우선하라 (0) | 2021.07.19 |