태그 달린 클래스를 사용하지 말자
class Figure {
enum Shape { RECTANGLE, CIRCLE };
// 현재 모양을 나타내는 태그 필드
final Shape shape;
double length;
double width;
double radius;
Figure(double length, double width) {
shape = Shape.RECTANGLE;
this.length = length;
this.width = width;
}
Figure(double radius) {
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);
}
}
}
Java
복사
•
이렇게 클래스 내부에 태그를 달고 태그에 맞춰 동작이 달라지는 클래스를 구현하면, enum 타입 선언부터 태그 필드, switch문 등 쓸데 없는 코드가 많아지고 가독성도 좋지 않다. 또한 메모리도 불필요하게 많이 차지하게 되고, 필드를 final로 두고 싶으면 생성자 호출 시에 쓰이지 않는 필드들까지 초기화해야한다. 쉽게말해 장황하고 오류가 발생하기 쉽고 비효율적이다.
따라서 태그 달린 클래스를 클래스 계층 구조로 변환하여 사용하자
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; }
}
Java
복사
•
이렇게 클래스 계층 구조로 작성하게되면 간결하고 명확하며, 사용되지 않는 코드도 없고, 불필요한 메모리 낭비도 없다. 또한 필드들을 final로 선언하여, 초기화를 빠뜨린 필드가 없는지 컴파일러가 확인해 주기도 한다.
•
또한 자연스러운 계층 관계를 반영할 수 있어 아래처럼 유연하게 확장하거나 변경할 수 있다.
class Square extends Rectangle {
Square(double side) { super(side, side); }
}
Java
복사