아이템 19 : 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라
메서드를 재정의하면 어떤 일이 일어나는지를 정확히 정리하여 문서로 남겨야 한다. 달리 말하면, 상속용 클래스는 재정의할 수 있는 메서드들을 내부적으로 어떻게 이용하는지 문서로 남겨야 한다.
하지만 내부 메커니즘을 문서로 남기는 것만이 상속을 위한 설계의 전부는 아니다. 효율적인 하위 클래스를 큰 어려움 없이 만들 수 있게 하려면 클래스의 내부 동작 과정 중간에 끼어들 수 있는 훅(hook)을 잘 선별하여 protected 메서드 형태로 공개해야 할 수도 있다. 드물게는 protected 필드로 공개해야 할 수도 있다.
상속용 클래스를 시험하는 방법은 직접 하위 클래스를 만들어보는 것이 '유일'하다.
널리 쓰일 클래스를 상속용으로 설계한다면 문서화한 내부 사용 패턴과, protected 메서드와 필드를 구현하면서 선택한 결정을 책임져야 함을 인식해야 한다. 이 결정들이 그 클래스의 성능과 기능에 영원한 족쇄가 될 수 있다. 그러니 상속용으로 설계한 클래스는 배포 전에 반드시 하위 클래스를 만들어 검증해야 한다.
상속을 허용하는 클래스가 지켜야 할 제약이 아직 몇 개 남았다. 상속용 클래스의 생성자는 직접적으로든 간접적으로든 재정의 가능 메서드를 호출해서는 안 된다.
clone과 readObject 모두 직접적으로든 간접적으로든 재정의 가능 메서드를 호출해서는 안 된다.
보통의 구체 클래스를 그 내부만 수정했음에도 이를 확장한 클래스에서 문제가 생겼다는 버그 리포트를 받는 일이 드물지 않다.
이 문제를 해결하는 가장 좋은 방법은 상속용으로 설계하지 않은 클래스는 상속을 금지하는 것이다.
상속을 금지하는 방법은 두 가지다.
하나는 둘 중 더 쉬운 쪽은 클래스를 final로 선언하는 방법이다.
두 번째는 모든 생성자를 private이나 package-private으로 선언하고 public 정적 펙터리를 만들어주는 방법이다.
핵심 정리
상속용 클래스를 설계하기란 결코 만만치 않다. 클래스 내부에서 스스로를 어떻게 사용하는지 모두 문서로 남겨야 하며, 일단 문서화한 것은 그 클래스가 쓰이는 한 반드시 지켜야 한다. 그러지 않으면 그 내부 구현 방식을 믿고 활용하던 하위 클래스를 오동작하게 만들 수 있다. 다른 이가 효율 좋은 하위 클래스를 만들 수 있도록 일부 메서드를 protected로 제공해야 할 수도 있다. 그러니 클래스를 확장해야 할 명확한 이유가 떠오르지 않으면 상속을 금지하는 편이 나을 것이다. 상속을 금지하려면 클래스를 final로 선언하거나 생성자 모두를 외부에서 접근할 수 없도록 만들면 된다.
'언어 > JAVA' 카테고리의 다른 글
[Effective Java] 인터페이스는 구현하는 쪽을 생각해 설계하라 (0) | 2020.03.19 |
---|---|
[Effective Java] 추상 클래스보다는 인터페이스를 우선하라 (0) | 2020.03.18 |
[Effective Java] 상속보다는 컴포지션을 사용하라 (0) | 2020.03.17 |
[Effective Java] 변경 가능성을 최소화하라 (0) | 2020.03.17 |
[Effective Java] public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라 (0) | 2020.03.16 |