Ответ
Преимущества:
- Повторное использование кода (Code Reuse) – дочерний класс наследует поля и методы родительского класса, избегая дублирования.
- Полиморфизм – объекты дочернего класса могут использоваться везде, где ожидается объект родительского класса, что позволяет создавать гибкие и расширяемые API.
- Создание иерархий типов – моделирует отношения «является» (is-a), что может сделать доменную модель более понятной.
Недостатки:
- Жесткая связь (Tight Coupling) – дочерний класс тесно связан с реализацией родителя. Изменения в родительском классе могут непреднамеренно сломать дочерние классы.
- Нарушение инкапсуляции – дочерний класс получает доступ к защищенным (
protected) членам родителя, что может привести к зависимости от внутренней реализации. - Хрупкость базового класса (Fragile Base Class Problem) – добавление нового метода в базовый класс может иметь непредвиденные последствия в наследниках.
- Ограничение множественного наследования – многие языки (Java, Swift, C#) не поддерживают наследование от нескольких классов, чтобы избежать сложностей (проблема ромба). В Swift эту роль берут на себя протоколы (интерфейсы).
Пример на Swift:
// Базовый класс
class Vehicle {
let numberOfWheels: Int
init(wheels: Int) {
self.numberOfWheels = wheels
}
func makeSound() {
print("Some generic vehicle sound")
}
}
// Дочерний класс
class Bicycle: Vehicle {
var hasBell: Bool
init(bell: Bool = true) {
self.hasBell = bell
super.init(wheels: 2) // Вызов инициализатора родителя
}
// Переопределение метода
override func makeSound() {
if hasBell {
print("Ring-ring!")
} else {
print("Squeak...")
}
}
}
// Использование полиморфизма
let myVehicle: Vehicle = Bicycle(bell: true)
myVehicle.makeSound() // Вывод: "Ring-ring!"
Альтернатива: Часто композиция (включение одного объекта в другой) предпочтительнее наследования, так как создает более гибкую и слабосвязанную архитектуру.