[JAVA] 컴포지션 vs 상속
클래스 설계시 상속으로 구현할지 컴포지션으로 구현할지 고민하다 이 부분을 공부해보았는데 생각보다 다양한 관점이 존재해서 한번 정리해보려고합니다.
보통 상속으로 구현한 부분은 컴포지션으로도 구현이 가능하고 반대로 상속으로 구현한부분은 컴포지션으로도 구현 가능합니다. 그렇다면 어떤 기준으로 상속과 컴포지션을 결정해야할까요?
컴포지션이란?
한 클래스가 다른 클래스를 포함하고 있는 경우를 말합니다.
아래 코드에서 Car 클래스는 Engin 클래스 타입의 맴버변수를 가짐으로서 Engin 은 Car의 컴포지션으로 볼 수 있습니다.
public class Car {
int price;
Engin engin;
String color;
public Car(int price, Engin engin, String color) {
this.price = price;
this.engin = engin;
this.color = color;
}
}
이때 Car 가 Engin 을 상속함으로써도 Engin 의 속성을 모두 이용할 수 있게 됩니다.
기준1 : has-a / is -a
일반적으로 컴포지션 과 상속을 결정하는 가장 보편적인 기준으로서
두 클래스가 has-a 관계일때는 컴포지션으로
반대로 is - a 관계일때는 상속으로 구현합니다.
기준2 : 기계적 이유
메모리적인 측면에서 두 방법을 고려해볼 수 있습니다. 아래 두가지 방법으로 box 를 생성했습니다. 두 방법에 대한 메모리 블럭을 그려보면 첫번째 box 변수는 힙 안에 [10,20,30]을 가리키고 있을 것입니다. 그리고 두번째 box 변수는 [rectangle의 주소값 , 30]을 들고 있고 rectangle 의 주소값은 다시 [10,20]을 가리키고 있을것입니다.
이에 기반해서 생각해보면 상속형 변수는 메모리에서 데이터를 한번에 가져올 수 있지만 컴포지션형 변수는 두번가져오게 되어 성능상 불이익이 발생할 수 있습니다. 작은 프로그램이라면 상관없겠지만 큰 규모에 빠른 성능이 필요하다면 컴포지션 보다는 상속을 선택할 수 있겠습니다.
// 상속
Box box = new Box(10,20,30)
// 컴포지션
Rectanle rectangle = new Ranctangle(10,20)
Box box = new Box(rectangle , 30)
기준3 : 용도의 차이
다형성을 필히 사용해야 하는 경우 상속을 선택해야합니다.
기준4: 관리적 관점
- 깊은 상속으로 구현되었을때 상위의 클래스는 수정이 어렵습니다. -> 상속의 단점
- 컴포지션은 getter / setter 등 그외 중복코드가 상속에 비해 발생합니다 -> 컴포지션의 단점