본문 바로가기
Effective JAVA 2판

Effecitve JAVAItem20 태그 달린 클래스 대신 클래스 계층을 활용하라

by BroBroBro 2015. 6. 30.

------------------------------------------------

본글은 Effective JAVA 2판의 책의 내용을 토대로 작성하였으며
지극히 주관적인 사항들이 많이 있으므로 가려서 읽으시기바랍니다.
잘못된 내용이 있거나 의견이 있으시다면 언제든 댓글로^^~!

------------------------------------------------

CHAPTER 4 클래스와 인터페이스

4장에서는 클래스와 인터페이스를 설계할때 이용할 수 있는 강력한 요소들을 많이 갖추고 있다고 한다. 

[Item 13] 클래스와 그 멤버의 접근 권한을 최소화하자 부터 보도록 하자 

Item14 public 클래스 안에는 public 필드를 두지말고 접근자(accessor) 메소드를 사용한라
Item15 변경 기능성을 최소화 하라 
Item16 계승하는 대신 구성하라
Item17 계승을 위한 설계와 문서를 갖추거나, 그럴 수 없다면 계승을 금지하라
Item18 추상 클래스 대신 인터페이스를 사용하라
Item19 인터페이스는 자료형을 정의할 때만 사용하라
Item20 태그 달린 클래스 대신 클래스 계층을 활용하라
Item21 전략을 표현하고 싶을 때는 함수 객체를 사용하라
Item22 멤버 클래스는 가능하면 static으로 선언하라.

--page01


예제부터 볼까요?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Figure {
    enum Shape {
        RECTANGLE, CIRCLE
    };
 
    // Tag field - the shape of this figure
    final Shape shape;
 
    // These fields are used only if shape is RECTANGLE
    double length;
    double width;
 
    // This field is used only if shape is CIRCLE
    double radius;
 
    // Constructor for circle
    Figure(double radius) {
        shape = Shape.CIRCLE;
        this.radius = radius;
    }
 
    // Constructor for rectangle
    Figure(double lengthdouble 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();
        }
    }
}
cs

한클래스에서 우선 두가지 이상의 기능을 하고있다. 눈에 보이나? 사각형과 원이라는?

여기에는 상투적인(boiler plate)코드가 있을것인데 그것이 Swithc문이다.

단점 : 가독성저하, 메모리낭비, final선언 불가, 앞에3가지단점을 종합면 오류발생가능성 증가


어떻게 해결하는지 예제를 보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
abstract class Figure {
    abstract double area();
}
 
class Circle extends Figure {
    final double radius;
 
    Circle(double radius) {
        this.radius = radius;
    }
 
    double area() {
        return Math.PI * (radius * radius);
    }
}
 
class Rectangle extends Figure {
    final double length;
    final double width;
 
    Rectangle(double lengthdouble width) {
        this.length = length;
        this.width = width;
    }
 
    double area() {
        return length * width;
    }
}
cs

하위자료형정의(Subtyping)로서 해결하였다.

한클래스는 한가지의 기능만을 가지게 만들자, 독립적으로 작업이 가능하게 만들자구요.

책에서이런말을 한다 Switch등 tag가 보인다면 Refactoring를 생각해보자고...


그리고 만약에 사각형을 추가한다고 하면 

1
2
3
4
5
class Square extends Rectangle {
    Square(double side) {
        super(side, side);
    }
}
cs

맨위에 소스에 Square를 추가한다고 생각해보자? ENUM추가, CASE추가 등등 flexible 하지 못하다.

이상~!