본문 바로가기

Language/Java Plus

Effective JAVA - Item19 : 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라.

 

 

 

 

결론

상속을 해서 확장을 했을 때 많은 문제를 일으킨다. 해결 방법은 클래스 상속시 상속을 위해 설계하고 설명해주는 문서를 만드는 것이다. 그렇게 만든 클래스가 아니라면 해당 클래스의 상속을 금지시켜라

 

 

 

 

상속이 위험한 이유

내가 어떤 클래스를 상속해서 클래스를 만든다고 가정하자. 하지만, 그 상위 클래스는 내가 수정할 수 있는 나의 코드가 아닌 다른 패키지의 클래스를 사용한다면 내가 통제를 할 수가 없다. 따라서, 다음 릴리즈 등에서 변경시 내가 할 수 있는 것이 없다. 따라서 코드 수정, 안정성 면에서 다소 위험하다.

 

 

 

 

상속을 할 수 있게 하는 방법 : 상속을 위한 설계와 API 문서 작성

 

1. 메서드를 재정의하면 메서드 내부가 어떻게 동작하는지 상세히 정리하여 문서로 남겨야 한다.

-> 어떤 순서로 호출되는지, 각각의 호출 결과가 이어지는 출력에 어떻게 영향을 주는지, 해당 메서드가 다른 메서드 어디에 이용되는지 등

-> 실제 API 문서에서는 Implementation Requirements 부분을 확인하면 된다.

 

 

2. 재정의 메서드 내부 동작에 중간에 끼어들 수 있는 훅을 protected로 설정할지 private로 설정할지 정해야 한다.

-> 예를 들어, AbstractList의 clear 메서드는 내분에서 removeRange메서드를 사용하고 이를 알맞게 재정의한다면 속도가 향상된다. 따라서 removeRang를 protected로 설정하였다.

-> "이와 같이 재정의 메서드 내부의 메서드에 접근 범위도 설정을 해야한다."

 

 

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

-> 하위 클래스 객체 생성 중간에 상위 클래스의 생성자가 호출되기에 하위 클래스의 객체가 생성도 전에 하위 클래스의 메서드가 호출될 수 있다.

-> Cloneable 과 Serializable 의 메서드인 clone과 readObject 메서드 사용시에도 주의해야 하는데, 새로운 객체를 생성하므로 생성자와 같은 역할을 하기 때문이다.

 

 

 

 

상속을 위해 설계되지 않고 API가 없다면 상속을 금지시켜라

-> 1. Class를 final로 선언

-> 2. 모든 생성자를 private이나 package-private로 설정 후, public 정적 팩터리 메서드를 제공

-> 둘 다 좋은 방법

-> 상속 대신 전달 클래스, 래퍼 클래스를 활용하는 것도 좋은 방법

 

 

 

 

예제 코드

https://github.com/mokjaemin/EffectiveJAVA

 

GitHub - mokjaemin/EffectiveJAVA: Study Files Of Effective JAVA

Study Files Of Effective JAVA. Contribute to mokjaemin/EffectiveJAVA development by creating an account on GitHub.

github.com