상속을 고려한 설계화,문서화란?
1.상속용 클래스는 재정의할수있는 메서드들을 내부적으로 어떻게 이용하는지 문서로 남겨야한다.
->재정의 가능 메서드를 호출할수있는 모든상황을 문서로 남겨야한다.
public boolean remove(Object o)
주어진 원소가 이 컬렉션아에 있다면 그 인스턴스를 하나 제거한다
이컬렉션안에 Object.equals(o,e)참인 원소 e가 하나이상있다면 그중 하나를 제거
주어진 원소가 컬렉션안에있었다면 호출결과 true를 반환
2.클래스의 내부 동작과정 중간에 끼어들수있는 훅을 잘 선별하여 protected메서드 형태로 공개해야할수도 있다.
java.util.AbstractList의 removeRange
protected void removeRange(int fromIndex, int toIndex)
List구현체의 최종사용자는 removeRange메서드에 관심이없지만
이 메서드를 제공한 이유는 단지 하위클래스에서의 부분리스트의 clear메서드를 고성능으로 만들기 쉽게 하기 위해서이다.
상속용 클래스를 설계할때 어떤메서드를 protected로 노출해야할까?
->실제 하위 클래스를 만들어 시험해보는 것이 최선
4.상속용으로 설계한 클래스는 배포전에 반드시 하위클래스를 만들어 검증해야한다.
5.상속용 클래스의 생성자는 직접적으로든 간접적으로든 재정의 가능 메서드를 호출해서는안된다.
->이 규칙을 어기면 프로그램이 오동작함
->상위클래스의 생성자가 하위클래스의 생성자보다 먼저 실행되므로 하위클래스의 재정의 메서드가 하위클래스생성자보다 먼저 호출
해당 규칙을 어긴코드
public class Super{
//잘못된 예- 생성자가 재정의가능 메서드를 호출한다.
public Super(){
overrideMe();
}
public void overrideMe(){
}
}
하위클래스 코드
public final class Sub extends Super {
//초기화되지 않은 필드, 생성자에서 초기화한다
private final Instant instant;
Sub(){
instant=Instant.now();
}
//재정의 가능 메서드, 상위클래스의 생성자가 호출한다.
@Override
public void overrideMe() {
super.overrideMe();
}
public static void main(String[] args) {
Sub sub= new Sub();
sub.overrideMe();
}
}
instant를 두번 출력하리라 기대했겠지만
첫번째는 null을 출력
상위클래스의 생성자는 하위클래스이 생성자가 인스턴스 필드를 초기화하기전에
overrideMe를 호출하기 때문
->clone이 잘못되면 복제본 뿐 아니라 원본객체에도 피해를 줄수있음
7.Serializable을 구현한 상속용 클래스가 readResolve나 writeReplace메서드를 갖는다면 이 메서드들은 private이 아닌 protected로 선언해야한다.
->상속을 허용하기위해 내부구현을 클래스 API로 공개하는 예 중 하나
8.그외 일반적은 구체클래스는?
->이런 클래스들은 final도 아니고 상속용으로 설계되거나 문서화되지 않음.
->상속용으로 설계하지않은 클래스는 상속을 금지
1)클래스를 final로 선언
2)선택자는 모든 생성자를 private이나 package-private으로 선언