You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
packagemachine.domain.calculate;
//package-Private 톱 클래스classAdder {
...
}
위의 코드에서 Adder 클래스는 Calculator에게서 밖에 사용되지 않는다.
하지만 톱 클래스에 대한 가장 낮은 접근 제어 수준은 package-private임으로 같은 패키지라면 어떤 클래스든 Adder를 사용할 수 있다.
불필요하게 접근 제어 메커니즘이 넓다
packagemachine.domain.calculate;
publicclassCalculator {
publicintadd(inta, intb) {
returnadder.add(a, b);
}
....
// 한 클래스에서만 사용하는 클래스를 이너 클래스로 위치// 이렇게 함으로써 Adder는 바깥 클래스 하나에서만 접근 가능함privatestaticclassAdder {
...
}
}
한 클래스에서만 사용하는 톱레벨 클래스를 사용하는 쪽에 중첩 기키면 바깥 클래스 하나에서만 접근할 수 있도록 할 수 있다.
멤버에 부여할 수 있는 접근 제어 수준
멤버: 필드, 메서드, 중첩 클래스, 중첩 인터페이스
멤버에 적용할 수 있는 접근 제어 수준은 4가지
private: 멤버를 선언한 톱레벨 클래스에서만 접근 가능
package-private: 멤버가 소속된 패키지 안의 모든 클래스에서 접근 가능 (default)
protected: package-private + 이 멤버를 선언한 하위 클래스에서 접근 가능
public: 모든 곳에서 접근 가능
멤버에 대한 접근 제어 원칙
클래스의 공개 API를 세심히 설계한 후, 그 외의 모든 멤버는 private으로 만들자
그런 다음 오직 같은 패키지의 다른 클래스가 접근해야 하는 멤버에 한해 package-private으로 풀어주자
그리고 권한을 풀어주는 일을 자주 하게 된다면 컴포넌트 분해가 필요하다는 메시지가 아닌지 생각해보자
private, package-private은 모두 구현에 해당함으로 보통은 공개 API에 영향을 주지 않는다.
단 Serializable을 구현한 클래스에서는 그 필드들도 의도치 않게 공개 API가 될 수도 있다
pacakge-private 에서 protected로 바꾸면?
public 클래스에서 pacakge-private, protected로 멤버의 접근 제어 수준을 바꾸는 순간 접근 가능한 범위가 굉장히 넓어진다.
public 클래스의 protected 멤버는 공개 API이다.
공개 API는 영원히 지원해야 하는 대상
따라서 멤버의 접근 제어 수준이 protected인 것은 적을 수록 좋음
멤버 접근성을 좁히지 못하는 상황
상위 클래스의 메서드를 재정의하고 싶은 경우를 생각해보자
상위 클래스의 메서드를 재정의할 때는 그 접근 수준을 상위 클래스에서보다 좁게 설정할 수 없다.
이는 멤버 접근성을 원하는대로 좁히지 못하는 제약 상황
이러한 제약 상황은 왜 있을까?
상위 클래스의 인스턴스는 하위 클래스로 대치될 수 있어야 한다는 리스코프 치환 원칙 때문
코드를 테스트하는 목적으로 접근 제어 수준 완화
코드를 테스트하려는 목적으로 접근 제어 범위를 넓히려 할 때가 있다.
클래스의 private 멤버를 package-private까지 풀어주는 것은 허용 가능
그 이상은 안됨
이 위로는 공개 API로 관리의 대상이 되어야 하기 때문
public 클래스의 인스턴스 필드는 되도록 public이 아니어야 한다.
public 인스턴스는 필드에 담을 수 있는 값을 제한할 힘을 잃게 된다.
그 필드와 관련된 모든 것은 불변식을 보장할 수 없게 된다는 뜻
여기에 더해 필드가 수정될 때 Thread-Safe하지 않다.
이러한 문제는 정적 필드에서도 마찬가지 But 예외 있음
해당 클래스가 표현하는 추상 개념을 완성하는 데 꼭 필요한 구성요소로써의 상수라면 public 공개도 괜춘
다만 public static final은 반드시 기본 타입 값이나 불변 객체를 참조하도록 하자
가변 객체를 참조한다면 불이익(사이드 이펙트) 많다.
자바 9의 모듈
자바 9에서는 모듈 시스템이라는 개념이 도입되면서 암묵적으로 접근 수준이 추가되었음
패키지가 클래스의 묶음이라면 모듈은 패키지들의 묶음
모듈은 자신에 속하는 패키지들 중 공개할 것들을 선언한다.
protected 혹은 public 멤버라도 해당 패키지를 공개하지 않았다면 모듈 외부에서는 접근할 수 없다.
모듈 시스템을 활용하면 클래스를 외부에 공개하지 않으면서도 같은 모듈을 이루는 패키지 사이에서는 자유롭게 공유할 수 있다.
// 모듈 내부의 abc.test 패키지를 외부에 공개한다. moduleabcmodule { exportsabc.test; }