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

2023. 11. 28. 23:24java/이펙티브 자바

 

 - 클라이언트 코드가 필드를 직접 사용하면 캡슐화의 장접을 제공하지 못한다.

 - 필드를 변경하려면 API를 변경해야 한다.

   => 접근자 메서드를 사용해도 바꿔야 하는 건 마찬가지지만 점진적으로 바꿀 수 있다.

 

 - 필드에 접근할 때 부수 작업을 할 수 없다.

public class Point {
    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;}
}

 

 - package-private 클래스 또는 private 중첩 클래스라면 데이터 필드를 노출해도 문제가 없다.

   => 클라이언트 코드가 이 클래스 내부 표현에 묶여도 같은 패키지 안에서만 동작한다고 문제가 없다고 책에서는 말 하는데 흠.. 그래도 API가 커지면서 같은 패키지 내에 클래스가 추가 되면서 한번에 고쳐야 할 코드가 늘어나거나 부가 작업들이 클라이언트 코드에 덕지덕지 붙는 것은 지저분해 보일 것 같다.

 

자바 플랫폼 내부에도 이 규칙을 어긴 사례가 있는데 Dimension 클래스다.

public class Dimension extends Dimension2D implements java.io.Serializable {

    /**
     * The width dimension; negative values can be used.
     *
     * @serial
     * @see #getSize
     * @see #setSize
     * @since 1.0
     */
    public int width;

    /**
     * The height dimension; negative values can be used.
     *
     * @serial
     * @see #getSize
     * @see #setSize
     * @since 1.0
     */
    public int height;
    
    .
    .
    .
    
}

 

이 클래스를 사용한다면 클라이언트는 항상 내부 값이 변해서 다른 코드에 영향을 주지 않을까 주의를 기울여야 한다. 이럴땐 객체를 복사해서 쓰는데, 성능 문제로 이어질 수도 있다.

 

 

public  클래스의 필드가 불변이라면 그나마 단점이 조금 줄어들지만, 여전히 좋지 않다. API를 변경하지 않고 표현 방식을 바꿀 수 없고, 필드를 읽을 때 부수 작업을 수행할 수 없다.