Skip to content

Latest commit

 

History

History
86 lines (52 loc) · 3.87 KB

15_클래스_맴버_접근권한_최소화하라.md

File metadata and controls

86 lines (52 loc) · 3.87 KB

아이템 15. 클래스와 멤버의 접근 권한을 최소화하라

캡슐화

  • 잘 설계된 컴포넌트는 모든 내부 구현을 완벽히 숨겨, 구현과 api를 깔끔히 분리를 한다.

접근제어자 종류

|제어자|같은 클래스|같은 패키지|자손 클래스|전체| |:-:|:-:|:-:|:-:|:-:| |public|O|O|O|O| |protected|O|O|O|X| |default(package-private)|O|O|X|X| |pivate|O|X|X|X|


캡슐화 잘 설계하는 방법

모든 클래스와 멤버의 접근성을 가능한 한 좁혀야 한다.

1. 톱레벨 클래스나 인터페이스는 외부에서 쓸 이유 없으면 private-package 사용하자.

  • 그러면 api가 아닌 내부 구현이 되어 클라이언트 피해없이 언제든 교체, 수정가능

톱레벨(가장 바깥) 클래스나 인터페이스에 부여할 수 있는 접근 수준은 package-private, public 두 가지

2. 한 클래스에서 사용하는 package-private 톱레벨 클래스나 인터페이스는 private static으로 중첩시키자.

  • 톱레벨로 두면 같은 패키지 모든 클래스가 접근 가능하지만, 바깥 클래스 하나에서만 접근가능하게 하자.

3. public일 필요가 없는 클래스의 접근 수준을 package-private 톱레벨 클래스로 좁히자.

  • public 클래스는 그 패키지의 api인 반면, packate-private 클래스는 내부 구현에 속한다.

4. 공개 api를 제외한 모든 멤버는 private으로 만들자.

  • 그 다음 오직 같은 패키지의 다른 클래스가 접근하는 멤버에 한하여 package-private으로 만들자.

5. public 클래스의 인스턴스 필드는 되도록 public이면 안된다.

  • thread safe 하지 않기 때문이다.
    • public 가변 필드를 가지게 되면 담을 수 있는 값을 제한할 수 없어 불변식을 보장할 수 없고 필드 수정될때(락획득 같은) 다른 작업을 하지 못해서다.

Serializable을 구현한 클래스는 그 필드들도 의도치 않게 공개 api가 될 수도 있다.

6. 예외로 상수라면 public static final 필드는 상관없지만, 가변객체가 아닌 기본 타입 또는 불변객체만 참조 해야한다.

  • 가변객체를 참조하면 다른 객체를 참조를 못하지만, 참조된 객체 자체가 수정될 수 있는 문제가 발생한다.
  • 클래스에서 public static final 배열 필드를 두거나 이 필드를 반환하는 접근자 메서드를 제공해서는 안된다.
    • 길이가 0이 아닌 배열은 모두 변경이 가능하다.
  • 해결법 #1
    • 배열 private 변경, public 불변 리스트 추가
private static final Thing[] PRIVATE_CALUES = {...};
public static final List<Thing> VALUES = Collections.unmodifialbeList(Arrays.asList(PRIVATE_VALUES));
  • 해결법 #2
    • 배열 private 변경, 복사본 반환하는 public 메서드 추가 (방어적 복사)
private static final Thing[] PRIVATE_CALUES = {...};
public static final Thing[] values() {
  return PRIVATE_VALUES.clone();
}

모듈 시스템

  • 자바 9에서 추가되면서 두가지 암묵적 접근 수준 추가

개념

  • 패키지 클래스의 묶음이듯, 모듈은 패키지들의 묶음이다.
  • 모듈은 속해있는 패키지 중 공개(export)할 것들을 선언한다.
    • public 멤버여도 공개되지 않으면 접근할 수 없다.
  • 모듈 시스템을 활용하면 클래스를 외부에 공개하지 않으면서도 같은 모듈을 이루는 패키지 사이에서는 자유롭게 공유할 수 있다.

두가지 암묵적 접근수준 추가

  • 암묵적 접근 수준들은 각각 public, protected 수준과 같으나, 그 효과가 모듈 내부로 한정되는 변종

주의 사항

  • 모듈의 jar파일을 자신의 모듈 경로가 아닌 classpath에 두면 그 모듈안의 모든 패키지는 마치 모듈이 없는 것처럼 행동한다.