Menu
CoddyTech

Композиция против наследования

Часть раздела Объектно-ориентированное программирование путешествия по Dart на Coddy. Урок 82 из 110.

Вы узнали, что наследование создаёт отношение «является» — Dog — это Animal. Но есть и другой мощный подход: композиция, которая создаёт отношение «имеет». Вместо наследования поведения класс содержит экземпляры других классов и делегирует им работу.

Рассмотрим класс Car. При наследовании можно попробовать унаследовать класс Engine — но автомобиль не является двигателем, у него есть двигатель:

class Engine {
  void start() => print('Engine started');
}

class Car {
  final Engine _engine = Engine();  // Композиция: у Car ЕСТЬ Engine
  
  void start() {
    _engine.start();  // Делегировать вызов двигателю
    print('Car is ready to drive');
  }
}

void main() {
  var car = Car();
  car.start();
}

Ключевое преимущество композиции — гибкость. При наследовании ты ограничен одним родительским классом. При композиции можно объединять несколько компонентов и даже заменять их во время выполнения программы:

class ElectricEngine {
  void start() => print('Electric motor humming');
}

class HybridCar {
  Engine? _gasEngine;
  ElectricEngine? _electricEngine;
  
  HybridCar({bool useElectric = false}) {
    if (useElectric) {
      _electricEngine = ElectricEngine();
    } else {
      _gasEngine = Engine();
    }
  }
}

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

challenge icon

Задание

Легко

Давайте создадим компьютерную систему с помощью композиции! Вместо того чтобы пытаться заставить компьютер наследовать свои части, вы создадите отдельные классы компонентов и объедините их — ведь у компьютера есть CPU и есть память, это не CPU и не память.

Вы организуете код в три файла:

  • components.dart: создайте два класса компонентов, представляющих части компьютера:
    • Класс CPU с полями String brand и double speedGHz. Добавьте метод process(), который возвращает строку: [brand] processing at [speedGHz]GHz
    • Класс Memory с полем int sizeGB. Добавьте метод load(), который возвращает строку: Loading [sizeGB]GB of data
  • computer.dart: создайте класс Computer, который использует композицию для объединения компонентов. Ваш компьютер должен:
    • Иметь поле String name
    • Содержать экземпляры CPU и Memory (композиция — у компьютера ЕСТЬ эти части)
    • Принимать все необходимые значения через конструктор, чтобы создавать оба компонента внутри класса
    • Иметь метод boot(), который делегирует работу обоим компонентам и выводит три строки: имя компьютера, за которым следует starting..., затем результат вызова метода process у CPU, а затем результат вызова метода load у Memory
    • Иметь метод specs(), который возвращает строку с описанием системы: [name]: [brand] [speedGHz]GHz, [sizeGB]GB RAM
  • main.dart: импортируйте свои файлы и продемонстрируйте композицию в действии:
    • Создайте Computer с именем Workstation, с процессором Intel с частотой 3.5 GHz и 16 GB памяти
    • Вызовите метод boot()
    • Выведите результат вызова specs()

Обратите внимание, что класс Computer не расширяет CPU или Memory — он содержит их и делегирует им выполнение работы. Такую связь «имеет» и создаёт композиция!

Ожидаемый вывод:

Workstation starting...
Intel processing at 3.5GHz
Loading 16GB of data
Workstation: Intel 3.5GHz, 16GB RAM

Попробуйте сами

import 'computer.dart';

void main() {
  // TODO: Создайте Computer с именем "Workstation" со следующими характеристиками:
  // - процессор Intel с частотой 3.5 GHz
  // - 16 GB памяти

  // TODO: Вызовите метод boot()

  // TODO: Выведите результат specs()
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор Dart