상속용 클래스는 내부 구현을 문서로 남겨야 한다.
@implSpec을 사용할 수 있다.
반대로 내부 구현에 대한 이야기를 상세히 적어야 한다.
javadoc - d [loc] [ploc] -tag “[explain …]”
/**
* Example class for java documentation for extendable class
*/
public class ExtendableClass {
/**
* This method can be overridden to print any message.
*
* @implSpec
* Please use System.out.println().
*/
protected void doSomething() {
System.out.println("hello");
}
}
내부 동작 중간에 끼어들 수 있는 훅(hook)을 잘 선별하여 protected 메서드로 공개해야 한다.
상속용으로 설계한 클래스는 배포 전에 반드시 하위 클래스를 만들어 검증해야 한다.
상속용 클래스의 생성자는 재정의 가능한 메서드를 호출해서는 안 된다.
Cloneable(아이템 13)과 Serializable(아이템 86)을 구현할 때 조심해야 한다.
// 생성자에서 호출하는 메서드를 재정의했을 때의 문제를 보여준다. (126쪽)
public final class Sub extends Super {
// 초기화되지 않은 final 필드. 생성자에서 초기화한다.
private final Instant instant;
Sub() {
instant = Instant.now();
}
// 재정의 가능 메서드. 상위 클래스의 생성자가 호출한다.
@Override public void overrideMe() {
System.out.println(instant);
}
public static void main(String[] args) {
Sub sub = new Sub();
sub.overrideMe();
}
}
---
public class Super {
// 잘못된 예 - 생성자가 재정의 가능 메서드를 호출한다.
public Super() {
overrideMe();
}
public void overrideMe() {
}
}
상속용으로 설계한 클래스가 아니라면 상속을 금지한다.