DEV ℧ Developer Diary

[EffectiveJava] item16 - public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라.

public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라.

이번 4장의 클래스와 인터페이스의 경우, 캡슐화를 강조하는 듯하다. 이렇게 접근제어자와 외부에서의 내부 로직에 대한 접근 관련 항목이 많이 작성되어있다.

public 클래스의 필드

class Point {
    public double x;
    public double y;
}

이따금 인스턴스 필드들만 모아져 있는 아무목적없는 클래스가 작성되었을 경우 class가 public으로 선언 되어있으면 안된다. 이런 클래스의 경우 데이터 필드에 직접 접근 할 수 있어, 캡슐화의 이점을 제공하지 못한다. 해당 식은 불변식을 보장 할 수 없어서 객체지향적 코드작성에서는 지양해야할 코드이다.

이러한 클래스를 제공할 경우 (주로 entity, dto와 같은 경우) 해당 필드들을 private로 선언 해준뒤 getter나 setter를 이용해 간접적으로 필드에 접근하도록 만들어주자.

class Point {
    /* 필드를 private로 제어 */
    private double x;
    private double y;

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }

    /* 간접적으로 필드를 제어하도록 만든다. */
    public double getX() { return x; }
    public double getY() { return y; }

    public void setX(double x) { this.x = x; }
    public void setY(double y) { this.y = y; }
}

패키지 바깥에서 접근할 수 있는 클래스라면 접근자를 제공함으로써 클래스 내부 표현 방식을 언제든 바꿀 수 있는 유연성을 얻을 수 있다.

만약 필드를 public으로 공개한다면 이를 사용하는 클라이언트가 생겨날 것이므로 내부 표현 방식을 마음대로 바꿀 수 없게된다.

하지만 package-private(default) 클래스 혹은 private 중첩 클래스라면 데이터 필드를 노출한다 해도 크게 문제가 없다. 그 클래스가 표현하려는 추상 개념만 올바르게 표현해주면 된다.

이 방식은 클래스 선언 면이나, 이를 사용하는 클라이언트 코드면에서나 접근자 방식보다 깔끔하다. 클라이언트 코드가 이클래스 내부 표현에 묶이지만, 클라이언트도 어자피 이 클래스를 포함하는 패키지 안에서만 동작하는 코드이기 때문이다.

public 클래스의 불변 필드

public클래스의 필드가 불변이라면 직접 노출할 때의 단점은 줄어들지만 좋은 생각이 아니다. 불변식을 보장한다는 것 외에는 장점이 없기 때문이다.