본문 바로가기
Language/Python

[Python] 컴포지션(composition)

by 며루치꽃 2021. 12. 16.

컴포지션(composition)

컴포지션은 다른 클래스의 일부 메서드를 사용하고 싶지만, 상속은 하고 싶지 않을 경우 사용합니다.
일반적으로 상속을 했을 때, 부모 클래스가 변하면 자식 클래스는 계속 수정되어야 한다.
 
- 다른 클래스의 일부 메서드를 사용하고 싶지만, 상속은 하고 싶지 않을 경우 사용한다.
- 상속 관계가 복잡할 경우, 코드에 대해 상세한 이해가 어려워 상속을 할 경우 위험성이 증가
- 상속 관계일 경우, 부모 클래스가 변하면 자식 클래스를 계속 수정되어야 한다. 
 
class Robot:

    __population = 0

    def __init__(self, name, age):
        self.__name = name
        self.__age = age
        Robot.__population += 1

    @property
    def name(self):
        return f"yoon {self.__name}"

    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, new_age):
        if new_age - self.__age == 1:
            self.__age = new_age
        else:
            raise ValueError()

    def __say_hi(self):
        self.cal_add(1, 3)
        print(f"Greetings, my masters call me {self.__name}.")

    def cal_add(self, a, b):
        return a + b + 1

    @classmethod
    def how_many(cls):
        return f"We have {cls.__population} robots."


class Siri(Robot):
    def say_apple(self):
        print("hello my apple")


class SiriKo(Robot):
    def say_apple(self):
        print("안녕 사과")


class Bixby(Robot):
    def say_sanmgsung(self):
        print("hello my sangsung")
 
예를 들어, 부모 클래스인 cal_add 인스턴스 메서드가 기존: return 이 a + b에서 a + b + 1 로 변경되었을 때 단점은 다음과 같다.
 

1. 부모 클래스가 변하면 자식 클래스는 계속 수정되어야 한다.

 
만약 Robot을 상속받는 Siri, SiriKo, Bixby 클래스가 cal_add 메서드를 이용하고 있다면 인스턴스에서 요구사항이 다르게 적용될 때 메서드를 오버라이딩을 해야하는 등의 유지보수하기가 어려워진다.


2. 부모 클래스의 메서드를 오버라이딩 하는 경우 내부 구현 방식의 얕은 이해로 오류가 생길 가능성 증가


그리고 또 다른 단점은 메서드가 기존 cal_add를 상속을 받아서 사용하고 있는데 오버라이딩을 무리하게 할 경우, 증가한다.
 
위와 같은 이유로 유지보수를 좀 더 견고하기 위해서 컴포지션(Composition)을 사용한다.
 

컴포지션(Composition) 사용법

class BixbyCal:
    def __init__(self, name, age):
        self.Robot = Robot(name, age) # 클래스의 객체를 명시적으로 가져옴

    def cal_add(self, a, b):
        return self.Robot.cal_add(a, b)	# 클래스의 객체에 있는 메서드를 명시적으로 활용한다
 

예를 들어 BixbyCal 이라는 클래스를 만들 때, Robot의 cal_add 메서드가 필요하다고 가정하자. 이 경우 BixbyCal에 cal_add를 새로 정의해줘도 되지만 메서드가 복잡해지면 복잡해질수록 의도하지 않은 방향으로 흘러갈 수 있다. 예를 들어 복잡도가 큰 머신러닝 알고리즘일 경우, 그렇다면 그대로 복사하기 보다 부분적으로 가져오는 것이 좋다. 또한, 상속을 받고 사용하기에는 위험성이 증가한다. 그래서 컴포지션(Composition) 이 필요하다. 

 

1. __init__에 선언된 것 처럼 해당 클래스의 객체를 명시적으로 가져온다. 

2. 사용할 클래스의 객체에 있는 메서드를 명시적으로 활용한다. 

댓글