В чем разница между композицией и наследованием в ООП?

«В чем разница между композицией и наследованием в ООП?» — вопрос из категории ООП, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Композиция и наследование — это два фундаментальных способа организации отношений между классами в объектно-ориентированном программировании.

Наследование (is-a)

Создает отношение «является». Дочерний класс наследует свойства и методы родительского, может их расширять или переопределять.

class Vehicle {
    func move() { print("Moving") }
}

class Car: Vehicle { // Car IS-A Vehicle
    func honk() { print("Beep!" ) }
}
let myCar = Car()
myCar.move() // Унаследованный метод

Композиция (has-a)

Создает отношение «имеет». Класс содержит экземпляр другого класса в качестве свойства.

class Engine {
    func start() { print("Vroom!" ) }
}

class Car { // Car HAS-A Engine
    let engine = Engine()
    func drive() {
        engine.start()
    }
}
let myCar = Car()
myCar.drive() // Делегирует работу объекту Engine

Ключевые отличия и рекомендации

Критерий Наследование Композиция
Связь Жесткая (родитель-потомок) Гибкая (владелец-компонент)
Поведение Определяется на этапе компиляции Можно менять во время выполнения
Множественность Одиночное наследование (в Swift) Множественная композиция
Тестируемость Сложнее из-за тесной связи Проще (можно подменить mock-объект)

Практическое правило: предпочитайте композицию наследованию. Она снижает связанность кода, повышает гибкость и упрощает модульное тестирование. Используйте наследование, только когда есть четкое отношение «является разновидностью» и необходимо полное повторное использование кода родителя.