가끔 인스턴스 필드들을 모아놓는 일 외에는 아무 목적도 없는 클래스를 작성할 때가 있다.
class Point {
public double x;
public double y;
}
→ 따라서, 객체 지향 프로그래머는 필드를 모두 private
으로 바꾸고 public 접근자(getter)
를 추가한다!
class Point {
private double x;
private double y;
public Point(final double x, final double y) {
this.x = x;
this.y = y;
}
**public double getX() {
return x;
}
public double getY() {
return y;
}
public void setX(final double x) {
this.x = x;
}
public void setY(final double y) {
this.y = y;
}**
}
public
클래스라면 위와 같은 방식을 사용하자.
하지만,
package-private
,private
중첩 클래스라면 데이터 필드를 노출한다 해도 문제가 없다.
클래스가 표현하려는 추상 개념만 올바르게 표현해주면 된다.
자바 플랫폼 라이브러리에도 public
클래스의 필드를 직접 노출한 사례가 종종 있다!
java.awt.package
패키지의 Point
, Dimension
public
클래스의 필드가 불변이라면 직접 노출할 때의 단점이 줄어들긴 하지만, 여전히 좋은 생각은 아니다.
API를 변경하지 않고는 표현 방식을 바꿀 수 없다.
필드를 읽을 때 부수 작업을 수행할 수 없다.
public final class Time {
private static final int HOURS_PER_DAY = 24;
private static final int MINUTES_PER_HOUR = 60;
**public final int hour;
public final int minute;**
public Time(final int hour, final int minute) {
if (hour < 0 || hour >= HOURS_PER_DAY) {
throw new IllegalArgumentException("시간: " + hour);
}
if (minute < 0 || minute >= MINUTES_PER_HOUR) {
throw new IllegalArgumentException("분: " + minute);
}
this.hour = hour;
this.minute = minute;
}
}
**
*public
클래스는 절대 가변 필드를 직접 노출하지 말자. 불변 필드라면 노출해도 덜 위험하지만, 완전히 안심할 수는 없다.
하지만 package-private
클래스나 private
중첩 클래스라면 종종 필드를 노출하는 편이 나을 때도 있다.***