OOP & JAVA

[JAVA] 컴포지션 vs 상속

쉽코기 2021. 11. 1. 17:39

클래스 설계시 상속으로 구현할지 컴포지션으로 구현할지 고민하다 이 부분을 공부해보았는데 생각보다 다양한 관점이 존재해서 한번 정리해보려고합니다.

 

보통 상속으로 구현한 부분은 컴포지션으로도 구현이 가능하고 반대로 상속으로 구현한부분은 컴포지션으로도 구현 가능합니다. 그렇다면 어떤 기준으로 상속과 컴포지션을 결정해야할까요?

 

컴포지션이란?

한 클래스가 다른 클래스를 포함하고 있는 경우를 말합니다.

아래 코드에서  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 등 그외 중복코드가 상속에 비해 발생합니다 -> 컴포지션의 단점