Наследование (Inheritance) и Композиция (Composition) - это два различных подхода к построению объектно-ориентированных систем, позволяющие повторно использовать код и устанавливать отношения между классами. Оба используются для уменьшения дублирования кода и повышения его переиспользования, но делают это разными способами.
Наследование определяет отношение "является" (is-a). Класс-наследник (подкласс) наследует все атрибуты и методы родительского класса (суперкласса). Он может расширять или переопределять поведение родительского класса. Наследование предполагает сильную связь между классами. Изменения в родительском классе могут повлиять на поведение всех его наследников.
        
class Животное:
    def издать_звук(self):
        print("Общий звук животного")
class Собака(Животное): # Собака "является" Животным
    def издать_звук(self): # Переопределение метода
        print("Гав!")
class Кот(Животное): # Кот "является" Животным
    def издать_звук(self): # Переопределение метода
        print("Мяу!")
        
    
    В этом примере `Собака` и `Кот` наследуют от `Животное`. Они "являются" животными и переопределяют метод `издать_звук` для специфичного поведения.
Композиция определяет отношение "содержит" (has-a). Класс содержит экземпляры других классов в качестве своих атрибутов. Вместо наследования функциональности, класс использует функциональность других классов через их экземпляры. Композиция создает более слабую связь между классами. Изменения в одном классе, используемом в композиции, реже влияют на другие классы.
        
class Двигатель:
    def запустить(self):
        print("Двигатель запущен")
class Колесо:
    def катиться(self):
        print("Колесо катится")
class Автомобиль:
    def __init__(self):
        self.двигатель = Двигатель() # Автомобиль "содержит" Двигатель
        self.колеса = [Колесо() for _ in range(4)] # Автомобиль "содержит" Колеса
    def поехать(self):
        self.двигатель.запустить()
        for колесо in self.колеса:
            колесо.катиться()
        
    
    В этом примере, `Автомобиль` "содержит" `Двигатель` и `Колесо`. Он использует их функциональность, но не является ими. Это позволяет менять двигатель или тип колес независимо от класса `Автомобиль`. Композиция обеспечивает большую гибкость и уменьшает зависимость между классами.
Основные различия:
Когда использовать: