아래와 같이 인스턴스 필드를 모아 놓기만 하는 퇴보한 클래스를 작성하지 마라
public class UsedCar {
public int mileage;
public int price;
}
이런 클래스는
- 데이터 필드에 직접 접근할 수 있으므로, 캡슐화의 이점이 없다
- API 수정 없이 내부 표현을 바꿀 수 없다
- 외부에서 필드에 접근할 때, 부수 작업을 수행할 수 없다
- 불변식을 보장할 수 없다
만약 public 클래스의 필드를 아래와 같이 불변으로 만든다면, 불변식을 보장할 수는 있게 된다
하지만 나머지 단점은 여전히 존재한다
public final class UsedCar {
private static final int MILEAGE_MINIMUM = 0;
private static final int PRICE_MINIMUM = 0;
public final int mileage;
public final int price;
public UsedCar(int mileage, int price) {
if (mileage < MILEAGE_MINIMUM || price < PRICE_MINIMUM) {
throw new IllegalArgumentException("주행 거리와 가격은 0보다 커야 합니다.");
}
this.mileage = mileage;
this.price = price;
}
}
책에서는 이 대신 getter와 setter를 사용하는 것이 객체지향적이라는 말이 나온다
하지만 위의 좋지 않은 사례에 상대적으로 그렇다는 것이고, 이미 둘을 지양해야 할 이유를 미션 내에서 모두 체득하고 있다고 생각하기에,
getter와 setter를 넣은 코드는 생략하겠다
별개로 pakage-private 클래스, 혹은 private 중첩 클래스라면, 데이터 필드를 노출해도 괜찮다
pakage-private의 경우에는 패키지 내부에서만 사용되기에, 외부의 수정 없이 데이터 표현 방식을 바꿀 수 있기 때문이다
private 중첩 클래스는 범위가 더욱 좁아서, 외부 클래스까지만 수정 범위가 제한된다
public class UsedCar {
private int mileage;
private int price;
private Fuel fuel;
public UsedCar(int mileage, int price) {
this.mileage = mileage;
this.price = price;
this.fuel = new Fuel();
}
private void chargeFuel() {
fuel.amount = 100;
}
private class Fuel {
public int amount;
public Fuel() {
this.amount = 0;
}
}
}
https://taxol1203.github.io/effective%20java/EJ-Item16/