-두가지 이상의 의미를 표현할수있으며 그중 현재 표현하는 의미를 태그값으로 알려주는 클래스
태그 클래스의 예시
public class Figure {
enum Shpae{
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*length;
case CIRCLE:
return Math.PI(radius*radius);
default:
throw
new AssertionError(shape);
}
}
}
태그 달린 클래스의 단점?
1) 열거타입 선언, 태그 필드,Switch문등 쓸데없는 코드가 많다.
2) 여러 구현이 한 클래스에 혼합돼있어 가독성이 나쁘다.
3) 다른의미를 위한 코드도 함께하니 메모리도 많이 사용한다
4) 쓰지않는 필드를 초기화하는 불필요한 코드가 늘어난다.
태그 달린 클래스는 장황하고, 오류를 내기 쉽고 비효율적이다.
태그 달린 클래스는 계층구조를 어설프게 흉내낸 아류일뿐이다.
태그 달린 클래스를 계층구조로 바꾸는 방법
1)계층 구조의 루트가 될 추상클래스를 정의, 태그값에 따라 동작이 달라지는 메서드들을 루트 클래스의 추상 메서드로 선언
->Figure클래스에서는 area가 이러한 메서드에 해당함.
2)태그에상관없이 동작이 일정한 메서드들을 루트 클래스에 일반 메서드로 추가한다.
3)루트 클래스를 확장한 구체 클래스를 의미별로 하나씩 정의
->예시코드에서는 Figure를 확장한 원(Circle) 클래스, 사각형 클래스(Rectangle) 생성
태그 달린 클래스를 -> 클래스 계층 구조로 변환
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 Retangle extends Figure{
final double length;
final double width;
Retangle(double length, double width) {
this.length = length;
this.width = width;
}
@Override
double area() {
return length*width;
}
}
1)각 의미를 독립된 클래스에 담아 관련없는 데이터 필드를 모두 제거했음
2)각 클래스의 생성자가 모든 필드를 남김없이 초기화하고 추상 메서드를 모두 구현했는지 컴파일러가 확인해줌.
3)타입이 의미별로 존재하니 변수의 의미를 명시하거나 제한할수있고, 특정 의미만 매개변수로 받을수있다.
4) 타입 사이의 자연스러운 계층 관계를 반영-> 컴파일 타입검사능력을 높여줌.