개발을 하다보면 인스턴스 필드들만 모아놓는 목적만 가진 아래와 같은 클래스를 구성하는 경우가 있다.
public class Point{
public double x;
public double y;
}
이유는, 이러한 클래스 형태로 구현했을 때는 클라이언트에서 필드에 직접 접근할 수 있으므로 캡슐화의 이점을 제공하지 못한다는 단점이 있다. 또한 좀 더 알아보면,
- API를 수정하지 않고는 내부 표현을 바꿀 수 없다.
- public 필드로만 구성되어 있기 때문에 내부 표현을 변경하기 위해서는 API의 필드를 변경해야 한다. (메소드가 존재할 땐 파라미터에 따라 내부 표현이 변경 가능)
- 불변식을 보장할 수 없다.
- 클라이언트에서 직접적으로 필드에 접근하고 있으므로 클라이언트에 의해 언제든지 변경이 가능하다.
- 외부에서 필드에 접근할 때 부수적인 로직을 추가할 수 없다.
- Point.x 라는 필드를 조회했을 때 부수적인 로직(Ex. 연산 로직)을 추가할 수가 없다.
public 클래스가 필드값을 공개(pubilc 접근자)하게 되면 이를 사용하는 클라이언트가 생겨날 것이므로 내부 표현방식을 마음대로 바꿀 수 없게 된다.
객체지향 프로그래머의 데이터 캡슐화
그래서 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; }
}
이 처럼 구현하게 되면,
- 클래스의 내부 표현 방식을 언제든 바꿀 수 있는 유연성을 제공하게 된다.
- getter/setter 혹은 또 다른 메소드를 통해 로직을 언제든 추가할 수 있다.
하지만, package-private 클래스 혹은 private 중첩 클래스라면 데이터 필드를 노출한다고 해도 문제될 것이 없다.
Package-private : 같은 패키지 및 같은 클래스에서만 접근 가능
private 중첩 클래스 : 내부 클래스가 private 형태로 된 클래스
이런 방식을 사용하게 되면, 위에서 언급했듯이 API 내부 표현의 수정이 클라이언트 코드에 직접적으로 영향을 미칠 수 있으나, 클라이언트도 같은 패키지 안에서만 동작하는 코드이므로 매우 연관된 행동들을 가진 클래스일 것이고, 패키지 밖은 영향을 받지 않으므로 부담없이 내부표현을 바꿀 수 있다.
정리
public 클래스의 경우 가변 필드의 접근 제한자를 public으로 두면 안 되며, 불변 필드라고 해도 덜 위험하지만 안심할 수 없다. 만약 가변 필드를 노출하고 싶을 땐, package-private 클래스나 private 중첩 클래스를 활용해라.
![]() |
|
'자바' 카테고리의 다른 글
(이펙티브 자바) 아이템 22. 인터페이스는 타입을 정의하는 용도로만 사용하라 (0) | 2020.08.24 |
---|---|
(이펙티브 자바) 아이템 18. 상속보다는 컴포지션을 사용하라 (0) | 2020.08.18 |
(이펙티브 자바) 아이템 17. 변경 가능성을 최소화하라. (0) | 2020.08.18 |
(이펙티브 자바) 아이템 19. 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라 (0) | 2020.08.18 |
(이펙티브 자바) 아이템 14. Comparable을 구현할지 고려하라. (0) | 2020.08.17 |