주니어 개발자 성장기

아이템 19. 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라. 본문

Java/이펙티브 자바

아이템 19. 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라.

Junpyo Lee 2023. 9. 17. 17:16

개요

이전 아이템에서 상속 대신 컴포지션을 사용하라고 했지만 그래도 상속은 객체지향 프로그래밍의 가장 큰 특징들 중 하나이다. 코드의 재사용성을 높이는 방법 중 하나이다. 따라서, 상속을 허용할 때는 ‘잘’하는 것이 필요하다.




상속용 클래스는 내부 구현을 문서로 남겨야 한다.

하지만 이런 식은 “좋은 API문서란 ‘어떻게’가 아닌 ‘무엇’을 하는지를 설명해야 한다”라는 격언과는 대치되지 않나? 그렇다. 상속이 캡슐화를 해치기 때문에 일어나는 안타까운 현실이다. - 이펙티브 자바 3판 123p

어차피 상속으로 인해 캡슐화가 깨지기 때문에 내부 구현을 제대로 알아야 적절하게 오버라이딩할 수 있기 때문에, 상속용 클래스는 내부 구현을 자세하게 문서로 남겨야 한다는 것이다. 문서에 @implSpec과 함께 내부 구현에 관한 설명을 적어 놓자.




내부 동작에 끼어들 수 있는 훅을 잘 선별해서 protected 메서드로 만든다.

protected 메서드로 만들 훅에 대한 정확한 기준은 없으나 책에서는 상속용 클래스의 서브 클래스를 3개 정도 (가급적 다른 사람이)만들어서 필요한 부분을 찾을 것을 권장하고 있다.




상속용 클래스의 생성자는 직접적으로든 간접적으로든 재정의 가능 메서드를 호출해서는 안된다.

하위 클래스를 생성할 때, 상위 클래스의 생성자(super(~~))가 먼저 호출되는데, 이 때 재정의된 메서드는 하위 클래스의 내부 구현에 기반하고 있지만 하위 클래스의 멤버들은 초기화되지 않은 상태이기 때문에 의도치 않은 동작을 하게 된다. 따라서, 상속용 클래스의 생성자는 재정의 가능 메서드를 호출해서는 안된다. 같은 이유로 clone(), readObject()에서도 재정의 할 수 있는 메서드를 호출해서는 안된다.




결론

상속의 단점에도 불구하고 사용하고 싶다면 여러가지 제약들을 지키는 것이 좋다. 이것이 생각보다 까다롭기 때문에 상속을 사용하지 않고 상속을 금지하는 것도 좋은 방법이다.