Ограничения глубокого наследования
Часть раздела Объектно-ориентированное программирование путешествия по JavaScript на Coddy — урок 48 из 56.
Хотя наследование полезно, создание очень глубоких иерархий наследования (родитель → потомок → внук → правнук) может привести к проблемам. Чем глубже цепочка, тем сложнее становится понимать, поддерживать и изменять код.
Давайте посмотрим, что происходит при глубокой цепочке наследования:
// Базовый класс
class Vehicle {
constructor(type) {
this.type = type;
this.isRunning = false;
}
start() {
this.isRunning = true;
console.log(`${this.type} started`);
}
}
// Первый уровень наследования
class Car extends Vehicle {
constructor(make, model) {
super("Car");
this.make = make;
this.model = model;
this.wheels = 4;
}
honk() {
console.log("Beep beep!");
}
}
// Второй уровень наследования
class SportsCar extends Car {
constructor(make, model, topSpeed) {
super(make, model);
this.topSpeed = topSpeed;
}
race() {
this.start();
console.log(`Racing at ${this.topSpeed} mph!`);
}
}В этом примере SportsCar находится на втором уровне наследования. Это может привести к нескольким проблемам:
- Изменения в Vehicle могут неожиданно нарушить работу SportsCar
- По мере роста цепочки наследования становится сложнее отслеживать, откуда берутся методы и свойства
- Вы вынуждены использовать отношения «is-a», которые могут быть недостаточно гибкими
Задание
Завершите файл Robot.js, чтобы сделать робота функциональным. На данный момент робот собран, но ничего не умеет делать.
Что нужно сделать в <strong>Robot.js</strong>:
- Создайте компоненты speaker и mover внутри конструктора Robot
- Используйте компоненты в методах:
- В
greet(): Вызовитеthis.speaker.speak("Hello!"); - В
walkForward(): Вызовитеthis.mover.move("forward");
- В
Почему мы это делаем: Это композиция — робот строится путем объединения более мелких компонентов. У робота есть динамик (для разговора) и есть привод (для движения), а не наследование этих способностей.
Шпаргалка
Глубокие иерархии наследования (родитель → потомок → внук) могут привести к проблемам с поддержкой и отсутствию гибкости. Чем длиннее цепочка, тем сложнее становится понимать и изменять код.
Пример глубокой цепочки наследования:
class Vehicle {
constructor(type) {
this.type = type;
this.isRunning = false;
}
start() {
this.isRunning = true;
console.log(`${this.type} started`);
}
}
class Car extends Vehicle {
constructor(make, model) {
super("Car");
this.make = make;
this.model = model;
}
}
class SportsCar extends Car {
constructor(make, model, topSpeed) {
super(make, model);
this.topSpeed = topSpeed;
}
}Проблемы глубокого наследования:
- Изменения в базовых классах могут неожиданно нарушить работу дочерних классов
- Трудно отследить, откуда происходят методы и свойства
- Навязываются жесткие отношения типа «является» (is-a), которым не хватает гибкости
Композиция как альтернатива: Вместо наследования используйте композицию, где объекты имеют отношение «содержит» (have-a) с компонентами, объединяя более мелкие части для создания функциональности.
Попробуйте сами
import { Robot } from './Robot.js';
const myRobot = new Robot('Robo');
myRobot.greet(); // Должен вывести: Saying: "Hello!"
myRobot.walkForward(); // Должен вывести: Moving forwardВ этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Объекты и ключевое слово this
Краткий обзор: ОбъектыДобавление методов в объектыПонимание ключевого слова thisФункции-конструкторыКлючевое слово newИтоговое испытание7Наследование и ключевое слово extends
НаследованиеОтношение «is-a»Ключевое слово extendsМетод super()Наследование свойств и методовИтоговое испытание10Полиморфизм
Что такое полиморфизм?Переопределение унаследованных методовИспользование superИтоговое задание13Композиция против наследования
Отношения «has-a» и «is-a»Ограничения глубокого наследованияСоздание объектов2Организация кода
Что такое модули?Экспорт с помощью exportИмпорт с помощью importDefault против именованных экспортов5Инкапсуляция и доступ
ИнкапсуляцияПубличные и приватные поля классовПриватные методыЗадание на повторение8Организация кода ООП
Организация классов в модули11Проект: Отрисовщик фигур
Настройка: Класс Shape и экспортНаследование класса Circle14Система управления библиотекой
Проектирование библиотекиКласс Book с использованием композиции6Проект: Простой банковский счет
Класс BankAccountПополнение и снятие средств9Статические методы и свойства
Уровень класса против уровня экземпляраСтатические свойстваСтатические вспомогательные методыЗадание на закрепление