주제
"다른 패키지의 구체 클래스를 상속하는 것은 위험 하다."
문제점
// 문제점 : 메서드 호출과 달리 상속은 캡슐화를 깨뜨린다.
// = 상위 클래스가 어떻게 구현되는냐에 따라 하위 클래스의 동작에 이상이 생길 수 있다.
// = 상위 클래스는 릴리스마다 내부 구현이 변경될 수 있고 이에 따라 하위 클래스가 동작하지 않을 수 있다.
// 상위 클래스의 메서드를 재정의하는 것은 내부 모든 동작을 파악하기도 어렵고 문서에 적혀있지 않은 경우도 존재한다
// 또한, 새로운 릴리스에서 내부 변경시 이에 맞추어 모두 수정해야 하기에 유연하지 못한다.
해결
// 해결책 : 컴포지션
// 방법
// 1. 기존의 클래스를 확장하는 대신, 새로운 클래스를 만들고 private 필드로 기존 클래스의 인스턴스를 참조하게 하자
// 2. 새 클래스의 메서드들은 기존 클래스 내의 대응하는 메서드를 호출해 그 결과를 반영한다.
// -> 이 방식을 전달(forwarding)이라고 하며 새 클래스의 메서드들을 전달 메서드라고 한다.
// 장점 : 기존 클래스의 내부 구현 방식의 영향에서 벗어나며, 새로운 메서드가 추가되더라도 영향을 받지 않는다.
// 상속방식은 구체 클래스 각각을 따로 확장해야 하고, 지원하고 싶은 상위 클래스의 생성자 각각에 대응하는 생성자를 별도로 작성해야한다.
// 컴포지션 방식은 한번 구현해두면 어떠한 Set의 구현체라도 계측할 수 있으며, 기존 생성자들과 함께 사용할 수 있다.
// 전달 클래스의 작성이 지루하겠지만, 재사용할 수 있다는 특징을 가진 전달 클래스를 인터페이스당 하나만 만들어두면
// 원하는 기능을 덧씌우는 래퍼클래스들을 아주 손쉽게 구현할 수 있다.
결론
// 상속은 강력하지만 캡슐화를 해친다는 문제가 있다.
// 상속은 상위 클래스와 하위 클래스가 is-a관계일때만 사용해야한다.
// is-a라고 안심할 수 없는게, 하위 클래스의 패키지가 상위 클래스의 패키지와 다르고,
// 상위 클래스가 상속을 위해 설계된게 아니라면 문제가 될 수 있다.
// 상속의 문제를 피하려면 컴포지션과 전달을 사용하자
// 특히, 래퍼 클래스로 구현할 적당한 인터페이스가 있다면 더욱 그렇다.
// 래퍼 클래스는 하위 클래스보다 견고하고 강력하다.
코드
https://github.com/mokjaemin/EffectiveJAVA
'Language > Java Plus' 카테고리의 다른 글
Effective JAVA - Item20 : 추상 클래스보단 인터페이스를 우선시하라. (0) | 2023.10.09 |
---|---|
Effective JAVA - Item19 : 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라. (0) | 2023.10.08 |
Effective JAVA - Item17 : 변경 가능성을 최소화하라. (0) | 2023.10.05 |
Effective JAVA - Item16 : public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라. (1) | 2023.10.05 |
Effective JAVA - Item15 : 클래스와 멤버의 접근 권한을 최소화하라. (0) | 2023.10.05 |