개요
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 클래스의 경우엔 종종 필드를 노출하는게 더 나을 때도 있다.
'Dev > Java' 카테고리의 다른 글
[Effective Java : Item 23] 태그 달린 클래스보다는 클래스 계층구조를 활용하라 (1) | 2024.02.13 |
---|---|
[Effective Java : Item 19] 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라 (2) | 2024.02.12 |
[Effective Java : Item 12] toString을 항상 재정의하라 (0) | 2024.02.04 |
[Effective Java : Item 4] 인스턴스화를 막으려거든 private 생성자를 사용하라 (0) | 2024.01.30 |
[Effective Java : Item 3] private 생성자나 열거 타입으로 싱글턴임을 보증하라 (1) | 2024.01.24 |