아이템 19 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라
메서드를 재정의하면 어떤 일이 일어나는지를 정확히 정리하여 문서로 남겨야 한다
재정의할 수 있는 메서드들이 내부적으로 어떻게 이용되는지
-> 클래스에서 공개된 메서드에서 재정의 가능 메서드를 호출하면 그 사실을 api 설명에 적어야한다
이렇게 되면 원래는 기술하지 않았어야 할 내부 구현 방식을 설명해야함
클래스의 내부 동작 과정 중간에 끼어들 수 있는 훅을 잘 선별하여 protected 메서드 형태로 공개해야 할 수도 있다
->
clear 메서드에서 removeRange 메서드를 호출하기 때문에 removeRange 메서드는 단순히 clear 메서드를 고성능으로 만들 수 있게 하기 위해서 제공된다
protected 메서드 하나하나가 내부 구현에 해당하기 때문에 최소화 해야하지만 그렇다고 너무 줄이면 상속으로 얻는 이점마저 사라질 수 있음
상속용 클래스를 시험하는 방법은 직접 하위 클래스를 만들어보는 것이 유일하다
-> 꼭 필요한 protected 멤버를 놓쳤다면 하위 클래스를 작성할 때 빈자리가 드러나고, 하위 클래스를 여러 개 만들동안 쓰이지 않는 protected 멤버는 사실 private이었어야 할 가능성이 크다
상속용 클래스의 생성자는 재정의 가능 메서드를 호출해서는 안 된다
->
instant가 두 번 출력될 것이라고 예상되지만, 상위 클래스 생성자가 먼저 실행되기 때문에 첫번째 출력에서는 null이 출력된다
clone과 readObject 메서드 또한 재정의 가능 메서드를 호출해서는 안 된다
-> 생성자와 비슷하게 하위 클래스의 상태가 수정/역직렬화 되기 전에 재정의한 메서드가 호출되어서 프로그램의 오작동으로 이어짐
클래스를 상속용으로 설계하려면 엄청난 노력이 들고 제약도 상당함
상속용으로 설계되지 않은 클래스는 상속을 금지할 것
아이템 20 추상 클래스보다는 인터페이스를 우선하라
자바8부터 인터페이스도 디폴트 메서드를 제공할 수 있게 되어 인스턴스 메서드를 구현 형태로 제공할 수 있게 됐다
반면 추상 클래스는 단일 상속밖에 할 수 없음
기존 클래스에도 손쉽게 새로운 인터페이스를 구현해넣을 수 있다
인터페이스는 믹스인 정의에 안성맞춤이다
믹스인이란? 원래의 주된 타입 외에도 특정 선택적 행위를 제공하는 것
이런 구조를 클래스로 만들려면 속성이 n개일때 지원해야 할 조합의 수가 2^n개가 됨
인터페이스에서 디폴트 메스드를 제공해서 프로그래머들의 일감을 덜어줄 수 있다
equals와 hashCode 같은 Object의 메서드를 디폴트 메서드로 제공해서는 안 된다
인터페이스와 추상 골격 구현 클래스를 함께 제공하는 식으로 인터페이스와 추상 클래스의 장점을 모두 취할 수 있다
인터페이스로 타입을 정의해놓고 골격 구현 클래스는 나머지 메서드들을 구현놓는다. 그러면 골격 구현 클래스를 확장하는 것만으로 인터페이스 구현에 필요한 일이 대부분 완료됨
인터페이스+골격 구현 클래스를 사용하면 타입 정의는 인터페이스처럼 자유로워지고, 골격 구현 클래스로 인터페이스 구현을 대부분 완료해놓을 수 있다
골격 구현 클래스는 상속으로 밖에 사용할 수 없기 때문에, 구조상 골격 구현 클래스를 상속할 수 없는 경우라도 골격 구현 클래스를 우회적으로 이용할 수 있다
-> 인터페이스를 구현한 클래스에서 골격 구현을 확장한 private 내부 클래스를 정의하고, 각 메서드 호출을 내부 클래스에 전달하는 것 = 시뮬레이트한 다중 상속
골격 구현 작성법
다른 메서드들의 구현에 사용되는 기반 메서드 선정
기반 메서드들을 사용해 직접 구현할 수 있는 메서드를 모두 디폴트 메서드로 제공
기반 메서드와 디폴트 메서드로 만들지 못한 메서드가 남아 있다면 골격 구현 클래스(추상 클래스)를 만들어 남은 메서드들 작성
골격 구현 클래스도 기본적으로 상속해서 사용하는 걸 가정하기 때문에 문서를 남겨야 함