컴포지션(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. 사용할 클래스의 객체에 있는 메서드를 명시적으로 활용한다.
'Language > Python' 카테고리의 다른 글
[Python] refactoring - 01. 추상화, 생성자주입을 통한 리팩토링 (0) | 2022.04.20 |
---|---|
[Python] Type Hint, Callable types (0) | 2021.12.19 |
[Python] 캡슐화(encapsulation) - @property 와 getter와 setter의 개념 (0) | 2021.12.14 |
[Python] 네임스페이스(namespace)에 대한 이해 (0) | 2021.12.08 |
[Python] 제네레이터(Generator)를 이용한 itertools 예시 (0) | 2021.12.01 |
댓글