DevPrep

Все темы › Объектно-ориентированное программирование (ООП)

Композиция vs Наследование

Junior

Суть

Наследование — отношение is-a («кнопка является view»): подкласс получает всё поведение родителя. Композиция — отношение has-a («экран имеет логгер»): объект собирается из частей и делегирует им работу. Общее правило: «предпочитайте композицию наследованию», наследуйтесь, когда действительно нужно расширить фреймворк (UIViewController) или модель предметной области честно иерархична.

Пример

// Inheritance: "is-a". A deep hierarchy is rigid.
class BaseViewController {}
class LoggingViewController: BaseViewController {}

// Composition: "has-a". Behaviour is injected and replaceable.
protocol Logger { func log(_ message: String) }
struct ConsoleLogger: Logger { func log(_ message: String) { print(message) } }
struct SilentLogger: Logger { func log(_ message: String) {} }

final class ProfileViewModel {
    private let logger: any Logger
    init(logger: any Logger = ConsoleLogger()) { self.logger = logger }
    func load() { logger.log("loading profile") }
}

ProfileViewModel().load()                       // prints
ProfileViewModel(logger: SilentLogger()).load() // prints nothing

Чтобы добавить логирование через наследование, нужен LoggingViewController, потом LoggingAnalyticsViewController... Комбинаторный взрыв. Композиция позволяет собрать любой набор поведений и подменить его в тестах.

Почему композиция обычно лучше

Когда наследование уместно

Потренируйтесь перед собеседованием

В DevPrep эти ответы превращаются в задачи на минуту: что напечатает код, найди баг, пробное собеседование. По задаче в день.

Скачать DevPrep в App Store