[이펙티브자바] 아이템18, 상속 보단 컴포지션을 사용하라.

[이펙티브자바] 아이템18, 상속 보단 컴포지션을 사용하라.

이번 글은 이펙티브자바 상속 보다 컴포지션을 사용하라

라는 주제에 맞게 상속, 컴포지션, 이 둘의 비교 및 언제

사용 해야 되는지에 대해서 간략하게 설명해보겠습니다.

목차

1. 상속이란?

2. 상속의 문제점

3. 컴포지션이란?

4. 상속 vs 컴포지션

5. 언제 상속을 사용해야 할까?

1. 상속이란?

상속은 객체지향에서 매우 중요한 역할을 수행합니다.

코드의 중복을 줄이고, 재사용성을 높히는데 있어 아주

큰 역할을 하는 기능 입니다.

자식 클래스는 부모 클래스를 상속 받아 자신의 기능 + 부모의 기능

이렇게 확장 할 수 있으며, 중복 코드를 최소화 해 여러 자식들이

중복 코드를 없애면서도 부모를 이용해 코드 재사용을 이룰 수 있습니다.

또, 부모 타입으로 자식 객체를 참조해 다형성을 이용할 수 있으며

이로인해 여러 타입의 객체를 하나의 배열에 넣어 일괄되게

사용할 수도 있습니다.

하지만 이러한 상속에도 여러 문제가 있습니다.

물론 많은 문제가 있겠지만 제가 지금 생각 나는것만

말씀드리도록 하겠습니다.

2. 상속의 문제

2-1. 캡슐화가 깨진다

캡슐화는 객체지향의 중요한 특성 중 하나입니다

외부로부터 내부의 데이터를 보호하고, 접근을 막아

객체의 역할과 책임을 명확하게 나타내며, 협력 하는데 있어

그 가이드라인을 제공해 주는 중요한 특성 입니다.

하지만 자식은 부모의 필드에 접근제어자가 protected 일 때

접근 가능 하며, 부모 클래스의 코드 변경이 자식에게도 영향을

미치는 사이드이팩트 역시 빈번하게 발생할 수 있습니다.

캡슐화는 객체의 변경 사항을 최대한 객체 내부로

모으는 역할도 하는데 상속의 경우 부모의 변경이

이를 상속 받고 있는 자식에게도 그 영향을 미칠 수 있어

문제가 됩니다.

2-2. 유지보수의 한계

상속이 한 단계, 두 단계이면 괜찮지만 세, 네 단계씩

상속을 해 내려가다보면 유지보수 하기 힘들어집니다.

이는 위 캡슐화 얘기와 일맥상통 하는 이야기인데

부모 클래스의 코드 한 줄이 아래 자식 클래스에

어떤 영향을 줄 지 알 수 없기 때문에 유지보수 역시

매우 힘들어 지는 경향이 있습니다.

2-3. 반쪽짜리 다형성

다형성은 객체지향을 이루는 매우 중요한 특성이자 기능 입니다.

하나의 클래스로 여러 객체를 참조해 같은 동작을 서로 다르게

실행 할 수 있게 해주는 기능 입니다.

이 다형성으로 우리는 매우 유연한 코드를 만들 수 있으며,

실행시점에 결정 되는 늦은 바인딩을 통해 상황에 알맞게

대처할 수 있습니다.

하지만 상속의 경우 다형성을 이용할 수 있지만 다형성에 꼭 필요한

오버라이딩이 강제 되어 있지 않아 이를 빼 먹을 수 있고,

부모의 인스턴스 역시 생성할 가능성이 있어 이 부분도 실수할 여지가 있습니다.

3. 컴포지션이란?

위 문제들로 인해 컴포지션을 사용하는게 많은 상황에서

좀 더 나은 해결책으로 여겨지고 있습니다.

일단 컴포지션은 내가 필요한 객체를 private 인스턴스변수로

클래스 내부에 가지고 있는 것을 말합니다. 즉 포함하는 것입니다.

이렇게 가지고 있으면서 필요할 때 마다 인스턴스메서드를 통해

요청 함으로써 협력을 기반으로 코드를 재활용 하는 것을 말합니다.

즉 다른 클래스를 내부에 가지고 있는 것을 말합니다.

이렇게 할 경우 변경 사항이 있어도 메서드의 시그니처(메서드명, 매개변수)만

바뀌지 않는다면 그 여파가 이 메서드를 사용하는 외부 클래스로

번질일은 없습니다. 사이드이팩트의 위험도 적습니다.

4. 상속 vs 컴포지션

대게 상속을 사용해야 하는 경우에서는 컴포지션을 사용할 수 있고,

반대로 컴포지션을 사용 해야 하는 경우에서는 상속을 사용할 수

있습니다.

하지만 많은 경우 컴포지션을 사용 하는 것이 상속의 단점을

커버 하면서 상속이 가져다 준 좋은 점들, 중복 제거 및 재사용성을

그대로 누릴 수 있다는 점이 컴포지션의 장점인 듯 합니다.

거기에 좀 더 완벽한 다형성까지 이용할 수 있습니다.

필요하면 인터페이스나 추상클래스를 이용해 다형성을

구현하도록 만들면 됩니다.

5. 언제 상속을 사용해야 할까?

상속은 is - a, 컴포지션은 has - a 관계라고 많이 표현 합니다.

정말 각 객체간의 관계가 is - a 관계일 때 상속을 선택 합니다.

하지만 이러한 관계에서도 하위 객체가 정말 딱, 상위 객체의

is - a 관계로써 하위 객체인지를 명확히 봐야 합니다.

그럼에도 안심할 수 없는 것은 어쨋든 캡슐화를 저해할 가능성과

확장성에 대한 문제가 있다는 것입니다. 자식객체가 부모 객체의

메서드를 이용해 어떤 작업을 할 때 알지 못하는 부모 객체 메서드의

기능 때문에 얘기치 않게 동작할 수 있으니 말입니다.

일단 이정도가 내가 공부한 내용인 듯 하다.

찬찬히 읽어 보면서 리팩토링 해야겠다.

오늘 배운 내용을 기억 하는데 이정도면

될 듯 하다.

from http://win-fly.tistory.com/8 by ccl(A) rewrite - 2021-09-19 16:27:11