상속용 클래스는 재정의할 수 있는 메서드들을 내부적으로 어떻게 이용하는지 문서로 남겨야 함
→ 자신의 다른 메서드에서 사용되는지, 어떤 순서로 호출하는지 …
→ api 문서 끝에 Implementation Requirements로 시작하는 절이 그 메서드의 내부 동작 방식을 설명하는 곳임 (메서드 주석에 @implSpec 태그를 붙여주면 자바독 도구가 생성해줌)
효율적인 하위 클래스를 쉽게 만들게 하기 위해 클래스의 내부 동작 과정 중간에 끼어들 수 있는 훅을 잘 선별해 protected 메서드(or 필드) 형태로 공개해야 할 수도 있음
→ ex) java.util.Abstract
의 removeRange
메서드 : 일반적으로 사용자들이 직접 호출할 필요가 없지만, 하위 클래스에서 부분리스트의 clear 메서드를 고성능으로 만들기 쉽게 하기 위해서 protected로 제공
상속용 클래스를 시험하는 방법은 직접 하위 클래스를 만들어 보는 것이 유일함
→ 상속용으로 설계한 클래스는 배포 전에 반드시 하위 클래스를 만들어 검증해야 함
상속용 클래스의 생성자는 직접적으로든 간접적으로든 재정의 가능 메서드를 호출해서는 안됨
public class Parent {
public Parent() {
overrideMe(); //상위 클래스에서 재정의 메서드 호출
}
public void overrideMe() {
System.out.println("부모 override 메서드 호출");
}
}
final class Child extends Parent {
private final Instant instant;
Child() {
instant = Instant.now();
}
// 재정의 가능 메서드
@Override
public void overrideMe() {
System.out.println(instant);
}
public static void main(String[] args) {
Child child = new Child();
child.overrideMe();
}
}
→ 오동작!
clone과 readObject 메서드는 생성자와 비슷한 효과(새로운 객체를 만듦)를 내기 때문에 모두 직간접적으로 재정의 가능 메서드를 호출해서는 안됨
⇒ 위처럼, 클래스를 상속용으로 설계하려면 엄청난 노력이 들고 그 클래스에 생기는 제약도 많음
⇒ 상속용으로 설계하지 않는 클래스는 상속을 금지하자!!
재정의 가능 메서드를 호출하는 사용 코드를 모두 제거하자
→ 메서드들 재정의해도 다른 메서드의 동작에 영향을 주지 않게끔 만들기 위함