어설프게 설계된 컴포넌트와 잘 설계된 컴포넌트의 가장 큰 차이는 바로 클래스 내부 데이터와 내부 구현 정보를 외부 컴포넌트로부터 얼마나 잘 숨겼느냐다.
https://jwdeveloper.tistory.com/175?category=830367
정보은닉의 장점
- 시스템 개발 속도를 높인다.
- 시스템 관리 비용을 낮춘다.
- 성능 최적화에 도움을 준다. - 다른 컴포넌트에 영향을 주지 않고 특정 컴포넌트만 프로파일링 가능
- 재사용성을 높인다.
- 테스트가 쉬워진다.
가장 중요한 원칙
모든 클래스와 멤버의 접근성을 가능한 좁혀라
톱 레벨 클래스 : 파일명과 클래스명이 동일한 클래스
1. 패키지 외부에서 쓸 일이 없다면 package-private (default)로 선언하자
- public으로 사용할 경우 외부에 공개되는 API가 되기 때문이다.
class topLevel {
public static void main(String[] args) {
nestedClass nestedClass = new topLevel.nestedClass();
nestedClass.test();
}
private static class nestedClass {
void test() {
System.out.println("nested class starting....");
}
}
}
중첩 클래스를 private static으로 선언하면 해당 상위 클래스 밖에 접근하지 못하며 외부에서는 접근할 수 있는 방법이 없다.
2. 모든 멤버를 private을 사용하자
- 패키지 외부에서 접근하는 멤버만 package-private으로 선언한다.
- 만약 위의 상황이 반복된다면 컴포넌트를 조금 더 쪼개야 하지 않는가에 대해서 생각해보자
3. 메서드를 재정의 할 경우 접근 수준을 상위 클래스에서 보다 좁게 설정할 수 없다.
- 하위 클래스의 메서드 접근 수준을 상위 클래스에서 보다 좁게 설정한다면 리스 코프 치환 원칙을 위반하는 행위이다.
- 상위 클래스에서 정의한 기능은 하위 클래스에서도 적용 가능해야 한다.
- 인터페이스를 implements 하는 클래스는 예외 사항 - 클래스는 인터페이스가 정의한 메서드를 모두 private으로 선언한다.
자식의 접근제어자는 부모의 접근제어자 보다 좁게 설정할 수 없다.
public class Parent {
public void test() {
}
}
class Child extends Parent {
//더 좁은 범위로 사용하였기 때문에 컴파일 오류 발생!
@Override
protected void test() {
super.test();
}
}
인터페이스의 구체 클래스의 접근제어자는 무조건 public
public interface ParentIml {
void test();
}
class concreteChild2 implements ParentIml{
/*부모는 private-package라도 자식은 항상 public으로 선언해야 한다.*/
@Override
public void test() {
}
}
4. public 클래스의 인스턴스 필드는 public으로 선언하지 말자
public 가변 필드를 갖는 클래스는 일반적으로 Thread-Safety하지 않기 때문
상수라면 public static final 필드로 공개해도 좋다.
네이밍은 대문자_ 로 구성한다. 반드시 불변 객체를 참조하도록 한다.
5. 클래스에서 public static final 배열 필드를 두지 말자
public static testClass[] PRIVATE_VALUES = {};
testClass에 대한 참조는 바꿀 수 없지만 배열 내의 내용이 변경 가능하다.
해결책 1. 접근 제한자를 private으로 만들고 public 불변 리스트 만들기
private static testClass[] PRIVATE_VALUES = {};
public static final List<testClass> VALUES =
Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));
해결책 2. 접근 제한자를 private으로 만들고 public메서드를 추가
private static testClass[] PRIVATE_VALUES = {};
public static final testClass[] values() {
return PRIVATE_VALUES.clone();
}
References
|
'Java > Java' 카테고리의 다른 글
(JAVA) 상속보다는 컴포지션을 사용하자 (0) | 2020.02.27 |
---|---|
(JAVA) private final 과 private static final (0) | 2020.02.21 |
(JAVA) The final keyword in Java (0) | 2020.02.11 |
(JAVA) 자바에서 hashCode의 사용 (0) | 2020.02.10 |
(JAVA) Immutable Class (0) | 2020.02.09 |