LINUX.ORG.RU

История изменений

Исправление 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, хорошо бы сделать композицию где будут отдельно ордер и процессор, но это будет еще больше текста в сообщении)