Menu
Coddy logo textTech

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

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

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

При наследовании Car может расширять Vehicle. При композиции Car содержит объект Engine:

<?php
class Engine {
    public function start(): string {
        return "Engine started";
    }
}

class Car {
    private Engine $engine;
    
    public function __construct() {
        $this->engine = new Engine();
    }
    
    public function start(): string {
        return $this->engine->start();
    }
}

$car = new Car();
echo $car->start();

Вывод:

Engine started

Класс Car не наследуется от Engine — он владеет одним экземпляром. Такой подход даёт значительные преимущества: можно заменить двигатель на другую реализацию, классы остаются слабо связанными, и вы избегаете жёстких иерархий, которые создаёт глубокое наследование.

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

В следующем уроке рассматривается внедрение зависимостей, которое непосредственно основывается на композиции, управляя тем, как объекты получают свои зависимости.

challenge icon

Задание

Легко

Давайте создадим компьютерную систему с использованием композиции, где Computer собирается из отдельных объектов-компонентов, а не наследует их. Это демонстрирует, как композиция позволяет создавать сложные объекты из более простых независимых частей.

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

  • Processor.php: создайте Processor class, представляющий ЦП. Используйте promotion конструктора, чтобы определить private $model (строка) и private $cores (integer). Добавьте method getSpecs(), который возвращает "[model] ([cores] cores)".
  • Memory.php: создайте Memory class, представляющий RAM. Используйте promotion конструктора, чтобы определить private $size (integer, представляющий объём в ГБ). Добавьте method getCapacity(), который возвращает "[size]GB RAM".
  • main.php: подключите оба файла компонентов и создайте Computer class, использующий композицию. Computer должен:
    • хранить объект Processor и объект Memory в качестве private properties
    • принимать в своём конструкторе model процессора, количество ядер и объём памяти
    • создавать объекты компонентов internally во время создания
    • иметь method describe(), который возвращает "Computer with [processor specs] and [memory capacity]"

    Вы получите три входных значения: model процессора, количество ядер и объём памяти в ГБ. Создайте Computer с этими характеристиками и выведите result вызова describe().

Обратите внимание, что Computer не расширяет Processor или Memory. Он содержит их. Эта связь "has-a" через композицию сохраняет независимость и возможность повторного использования каждого компонента, позволяя Computer при необходимости делегировать задачи своим частям.

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

<?php
require_once 'Processor.php';
require_once 'Memory.php';

class Computer
{
    // TODO: Определите приватные свойства для хранения объектов Processor и Memory

    // TODO: Конструктор должен принимать модель процессора, количество ядер и размер памяти
    // и создавать объекты компонентов внутри
    public function __construct()
    {
        // TODO: Создайте объекты Processor и Memory и сохраните их
    }

    // TODO: Реализуйте метод describe(), который возвращает
    // "Computer with [processor specs] and [memory capacity]"
    public function describe(): string
    {
        // TODO: Делегируйте объектам компонентов и верните отформатированную строку
    }
}

// Прочитать ввод
$processorModel = trim(fgets(STDIN));
$cores = intval(fgets(STDIN));
$memorySize = intval(fgets(STDIN));

// TODO: Создайте Computer с заданными характеристиками и выведите результат describe()

?>
quiz iconПроверьте себя

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

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

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