본문 바로가기

IT/이펙티브자바 3E

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

안녕하세요 남갯입니다.


오늘은 이펙티브 자바


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


를 포스팅 해보려고 합니다.



이 책에서는 상속을 염두하지 않았다면 상속하지 말라고 한다. 그렇다면 상속을 고려한 설계와 문서화란 무슨말일까?

상속용 클래스는 재정의할 수 있는 메서드들을 내부적으로 어떻게 이용하는지 문서로 남겨야한다.

final이 아닌 모든 메서드들이 어떤 순서로 호출하고 어떤 결과과 이어지는 처리에 어떤 영향을 주는지에 대한 정보를 담아야한다.

예를들어 AbstractCollection 에서 remove 메소드를 재정의 하지 않았다면 UnsupportOperationExeption을 던진다. 



상황에 따라 protected 메소드를 통해 필드나 메소드를 공개 해야할 수도 있다. 이렇게 만든 protected는 그 클래스의 성능과 기능에 영원한 족쇄가 될 수 있기 때문에 꼭 검증이 필요하다.



그리고 이런 상속클래스를 시험하는 방법은 직접 하위클래스를 만들어보는것이 유일한 테스트 방법이다. 


** 주의할점 상속용 클래스 생성자가 재정의 가능한 메서드를 호출 하면 안된다.


public class Super{

public Super(){
overrideMe(); // 잘못 된 예
}

public void overrideMe(){

}

}



public final class Sub extends Super{
private final Instant instant;

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

@Override
public void overrideMe() {
System.out.println(instant);
}
}
public void main(){
Sub sub = new Sub();
sub.overrideMe();
}


Instant가 두번 출력되리라 기대했겠지만

null을 출력한다. 하위클래스 생성자가 인스턴트 필드를 초기화 하기도 전에 overrideMe를 호출하기 때문이다 (부모클래스 초기화와 자식클래스의 초기화 순서의 문제 때문에)


** private, final, static 메서드는 재정의가 불가능하므로 생성자에 안심하고 호출 가능




Cloneable , Serializable 인터페이스는 상속용 설계의 어려움을 더해준다.


clone과 readObject 메서드는 생성자와 비슷한 효과를 낸다. 이들을 구현할때 생성자와 비슷하다는 점을 주의하자.



clone, readObject


clone과 readObject 모두 직접적 or 간접적으로 재정의 메서드를 호출 해서는 안된다. 


readObject의 경우 상태가 미처 다 역 직렬화 되기 전에 호출하고,


clone 복제본을 수정하기 전에 재 정의한 메서드를 호출한다. 



결론

따라서 클래스를 상송용으로 설계하려면 엄청난 노력이 들고 클래스안에 제약사항도 상당함을 알았다. 이런 문제들을 해결하기 위해선 상속용으로 설계하지 않은 클래스는 상속을 금지하는것이다.