История изменений
Исправление micronekodesu, (текущая версия) :
Но я могу сделать одну и ту же задачу и тем и тем способом. В целом понимаю их разницу и что они делают.
Какой хуже, какой лучше - я лично сказать не могу.
Потому что видно таки не понимаешь в чем разница. Наследование это когда у тебя класс делает то же самое, что базовый, только иначе. Композиция это когда у тебя один объект содержит другие объекты. Это решения для разных проблем.
Представь ты делаешь оплату в онлайн-магазине. У тебя есть класс PaymentProcessor
, у которого есть метод pay(amount)
. Потом ты наследуешь этот класс, делаешь PayPal(PaymentProcessor)
, SBP(PaymentProcessor)
, YandexMoney(PaymentProcessor)
и так далее, все они могут в этот pay(amount)
, но под капотом они разные.
И у тебя есть объект заказа, в котором список покупок, расчет суммы, скидки и все такое, и он должен выполнить оплату через этот PaymentProcessor
. Ты можешь, конечно, запихнуть весь код с заказом в базовый класс платежного класса, но тогда ты в одном месте смешиваешь разные по природе данные. В этом случае у тебя уже используется композиция, типа
class Order:
def __init__(self, payment_processor: PaymentProcessor):
self.payment_processor = payment_processor
def checkout(self):
price = self.calculate_price()
self.payment_processor.pay(price)
И сюда ты передашь уже процессор для выбранного способа оплаты при инициализации.
(пример не самый удачный, потому что на самом деле ордеру не нужно знать про payment_processor, хорошо бы сделать композицию где будут отдельно ордер и процессор, но это будет еще больше текста в сообщении)
Исходная версия micronekodesu, :
Но я могу сделать одну и ту же задачу и тем и тем способом. В целом понимаю их разницу и что они делают.
Какой хуже, какой лучше - я лично сказать не могу.
Потому что видно таки не понимаешь в чем разница. Наследование это когда у тебя класс делает то же самое, что базовый, только иначе. Композиция это когда у тебя один объект содержит другие объекты.
Представь ты делаешь оплату в онлайн-магазине. У тебя есть класс PaymentProcessor
, у которого есть метод pay(amount)
. Потом ты наследуешь этот класс, делаешь PayPal(PaymentProcessor)
, SBP(PaymentProcessor)
, YandexMoney(PaymentProcessor)
и так далее, все они могут в этот pay(amount)
, но под капотом они разные.
И у тебя есть объект заказа, в котором список покупок, расчет суммы, скидки и все такое, и он должен выполнить оплату через этот PaymentProcessor
. Ты можешь, конечно, запихнуть весь код с заказом в базовый класс платежного класса, но тогда ты в одном месте смешиваешь разные по природе данные. В этом случае у тебя уже используется композиция, типа
class Order:
def __init__(self, payment_processor: PaymentProcessor):
self.payment_processor = payment_processor
def checkout(self):
price = self.calculate_price()
self.payment_processor.pay(price)
И сюда ты передашь уже процессор для выбранного способа оплаты при инициализации.
(пример не самый удачный, потому что на самом деле ордеру не нужно знать про payment_processor, хорошо бы сделать композицию где будут отдельно ордер и процессор, но это будет еще больше текста в сообщении)