Backend/Java

[Effective Java : Item 16] public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라

김세진 2024. 2. 9. 22:14
반응형

 

 

 

 

개요

 

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

 

위같은 클래스는 필드에 직접 접근이 가능하므로 다음과 같은 캡슐화의 이점을 제공하지 못 한다.

 

1. API를 수정하지 않고 내부 표현을 바꿀 수 없다.

필드의 수정이 필요할 경우 구현의 세부사항이 외부로 노출되어 있기 때문에 API를 수정해야 한다. 이미 외부에서 해당 필드를 직접 사용하고 있을 경우 API 수정이 어렵게 되어 유지보수가 힘들어진다.

2. 불변식을 보장할 수 없다.

외부에서 직접 가변 데이터 필드에 접근할 수 있으므로 불변식을 보장할 수 없다. 모든 필드를 public final 로 선언한다면 불변식을 보장할 수 있지만, 1번과 동일한 문제가 남아있게 된다.

 

3. 외부에서 필드에 접근할 때 부수 작업을 수행할 수 없다.

정보를 얻거나 수정하려고 할 때 접근자를 사용하지 않고 직접 접근하게 되므로 부수 작업을 수행할 수 없다. 위의 Point를 예시로 들면 x 좌표를 수정할 때 음수값은 지정할 수 없다든지의 조치를 취할 수 없다.

 

따라서 public 클래스라면 가변 필드를 모두 private로 바꾸고 접근자를 통해 제어하도록 하여 캡슐화의 이점을 취할 수 있도록 하자.

 

class Point {
    private double x;
    private double 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 클래스 혹은 private 중첩 클래스라면 데이터 필드를 노출한다 해도 문제가 없다.  추상 개념만 올바르게 표현되면 오히려 접근자를 사용하는 것보다 훨씬 깔끔하다고 여겨질 수 있다.

 

package-private 클래스의 경우 동일한 패키지 내부에서만 동작하는 코드일 뿐이기 때문에 패키지 바깥 코드를 건드리지 않고 데이터 표현 방식을 바꿀 수 있기 때문이다. private 중첩 클래스의 경우는 해당 클래스의 외부 클래스까지로 제한되기 때문에 그 범위가 더 좁다.

 

하지만 접근자를 사용할 때 부수 작업을 수행할 수 있는 장점은 취할 수 없게 되므로 패키지의 규모에 따라 적절한 방법을 택하면 될 것 같다.

 

정리

 

1. public 클래스의 경우 절대 가변 필드를 직접 노출해서는 안 된다. (불변 필드더라도 권장하지 않음)

2. package-private나 private 클래스의 경우엔 종종 필드를 노출하는게 더 나을 때도 있다.

 

 

 

 

 

반응형