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.length;
this.length = length;
this.width = width;
}
double area() {
swtich(shape) {
case RECTANGLE:
return length * width;
case CIRCLE:
return Math.PI * (radius * radius);
default:
throw new AssertionError(shape);
}
}
}
열거 타입 선언, 태그 필드, switch문 등 쓸데없느 코드가 많다.
여러 구현이 한 클래스에 혼합돼 있어서 가독성이 나쁘다.
다른 의미를 위한 코드도 언제나 함께 하니 메모리도 많이 사용한다.
=> length, width, radius ...
필드들을 final로 선언하려면 해당 의미에 쓰이지 않는 필드들까지 생성자에서 초기화 해야한다.
=> 컴파일러가 잡아줄 수 없고 런타임에야 문제가 드러난다.
다른 의미(타입)를 추가하려면 코드를 수정해야한다.
=> switch문 ..
인스턴스의 타입만으로는 현재 나타내는 의미(타입) 를 알 길이 전혀 없다.
태그 달린 클래스는 장황하고, 오류를 내기 쉽고, 비효율적이다.
abstract class Figure {
abstract double area();
}
class Circle extends Figure {
final double radius;
Circle(double radius) {this.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;}
}
class Square extends Rectangle {
Square(double side) {
super(side, side);
}
}