이펙티브자바 아이템19

한주영·2023년 11월 8일
0

이펙티브자바

목록 보기
15/33

상속을 고려해 설계하고 문서화하라, 그러지않았다면 상속을 금지하라

상속을 고려한 설계화,문서화란?
1.상속용 클래스는 재정의할수있는 메서드들을 내부적으로 어떻게 이용하는지 문서로 남겨야한다.
->재정의 가능 메서드를 호출할수있는 모든상황을 문서로 남겨야한다.

public boolean remove(Object o)

주어진 원소가 이 컬렉션아에 있다면 그 인스턴스를 하나 제거한다
이컬렉션안에 Object.equals(o,e)참인 원소 e가 하나이상있다면 그중 하나를 제거
주어진 원소가 컬렉션안에있었다면 호출결과 true를 반환

2.클래스의 내부 동작과정 중간에 끼어들수있는 훅을 잘 선별하여 protected메서드 형태로 공개해야할수도 있다.

java.util.AbstractList의 removeRange

protected void removeRange(int fromIndex, int toIndex)

List구현체의 최종사용자는 removeRange메서드에 관심이없지만
이 메서드를 제공한 이유는 단지 하위클래스에서의 부분리스트의 clear메서드를 고성능으로 만들기 쉽게 하기 위해서이다.

상속용 클래스를 설계할때 어떤메서드를 protected로 노출해야할까?
->실제 하위 클래스를 만들어 시험해보는 것이 최선

  1. 상속용 클래스를 시험하는 방법은 직접 하위클래스를 만들어보는것이 유일하다

4.상속용으로 설계한 클래스는 배포전에 반드시 하위클래스를 만들어 검증해야한다.

5.상속용 클래스의 생성자는 직접적으로든 간접적으로든 재정의 가능 메서드를 호출해서는안된다.
->이 규칙을 어기면 프로그램이 오동작함
->상위클래스의 생성자가 하위클래스의 생성자보다 먼저 실행되므로 하위클래스의 재정의 메서드가 하위클래스생성자보다 먼저 호출

해당 규칙을 어긴코드

public class Super{
   
   //잘못된 예- 생성자가 재정의가능 메서드를 호출한다.
   public Super(){
      overrideMe();
   }
   public void overrideMe(){
   }
   

}

하위클래스 코드

public final  class  Sub extends Super {

    //초기화되지 않은 필드, 생성자에서 초기화한다
    private final Instant instant;

    Sub(){
        instant=Instant.now();
    }

    //재정의 가능 메서드, 상위클래스의 생성자가 호출한다.
    @Override
    public void overrideMe() {
        super.overrideMe();
    }

    public static void main(String[] args) {

        Sub sub= new Sub();
        sub.overrideMe();
    }
}

instant를 두번 출력하리라 기대했겠지만
첫번째는 null을 출력
상위클래스의 생성자는 하위클래스이 생성자가 인스턴스 필드를 초기화하기전에
overrideMe를 호출하기 때문

  1. clone과 readObject 모두 직접적이든 간접적이든 재정의 가능메서드를 호출해서는 안된다.
    ->상속용 클래스에서 Clonalbe이나 Serializavble을 구현할지 정해야한다면
    이들을 구현할때 따르는 제약도 생성자와 비슷하다는 점에 주의.

->clone이 잘못되면 복제본 뿐 아니라 원본객체에도 피해를 줄수있음

7.Serializable을 구현한 상속용 클래스가 readResolve나 writeReplace메서드를 갖는다면 이 메서드들은 private이 아닌 protected로 선언해야한다.

->상속을 허용하기위해 내부구현을 클래스 API로 공개하는 예 중 하나

8.그외 일반적은 구체클래스는?
->이런 클래스들은 final도 아니고 상속용으로 설계되거나 문서화되지 않음.

->상속용으로 설계하지않은 클래스는 상속을 금지

1)클래스를 final로 선언
2)선택자는 모든 생성자를 private이나 package-private으로 선언

profile
백엔드개발자가 되고싶은 코린이:)

0개의 댓글