Композиция и наследование
Часть раздела Объектно-ориентированное программирование путешествия по 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), но композиция особенно эффективна, когда вы собираете функциональность из независимых частей. Вы можете объединять несколько объектов, заменять их во время выполнения и тестировать компоненты изолированно.
В следующем уроке рассматривается внедрение зависимостей, которое непосредственно основывается на композиции, управляя тем, как объекты получают свои зависимости.
Задание
ЛегкоДавайте создадим компьютерную систему с использованием композиции, где Computer собирается из отдельных объектов-компонентов, а не наследует их. Это демонстрирует, как композиция позволяет создавать сложные объекты из более простых независимых частей.
Вы организуете код в трёх файлах:
Processor.php: создайтеProcessorclass, представляющий ЦП. Используйте promotion конструктора, чтобы определить private$model(строка) и private$cores(integer). Добавьте methodgetSpecs(), который возвращает"[model] ([cores] cores)".Memory.php: создайтеMemoryclass, представляющий RAM. Используйте promotion конструктора, чтобы определить private$size(integer, представляющий объём в ГБ). Добавьте methodgetCapacity(), который возвращает"[size]GB RAM".main.php: подключите оба файла компонентов и создайтеComputerclass, использующий композицию.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()
?>В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово $thisМетодыСвойстваКонструктор (__construct)Деструктор (__destruct)Повторение — простой калькулятор4Наследование
Основы наследованияКлючевое слово parent::Переопределение методовКлючевое слово finalАбстрактные классыПовторение — иерархия сотрудников7Инкапсуляция
Public, Protected, PrivateМодификаторы доступа подробноГеттеры и сеттерыСокрытие информацииПродвижение конструктора (8.0)Повторение — система учёта студентов10Продвинутые концепции ООП
Композиция и наследованиеВнедрение зависимостейАнонимные классыПеречисления (PHP 8.1)Файберы (PHP 8.1)Глубокое погружение в клонирование объектовГенераторы и итераторы2Пространства имён и автозагрузка
Введение в пространства имёнКлючевое слово useСтандарт автозагрузки PSR-4Автозагрузчик ComposerПовторение — структурированный проект5Интерфейсы и контракты
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовИнтерфейс и абстрактный классАннотация типов с интерфейсамиПовторение — калькулятор фигур8Магические методы
Введение в магические методы__toString и __debugInfo__get, __set, __isset, __unset__call и __callStatic__clone и клонирование объектов__serialize и __unserializeПовторение — пользовательская коллекция3Свойства классов
Свойства экземпляра и статические свойстваКонстанты в классахСтатические методы и свойстваПриватные и защищённые свойстваСвойства только для чтения (PHP 8.1)Повторение — менеджер банковского счёта6Полиморфизм
Повторение переопределения методовПолиморфизм через интерфейсыАннотации типов и объединённые типыПозднее статическое связываниеПовторение — обработчик платежей9Трейты
Введение в трейтыИспользование нескольких трейтовРазрешение конфликтов трейтовАбстрактные методы в трейтахТрейты и наследование12Паттерны проектирования, часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн StrategyПотренируйтесь самостоятельно: Онлайн-компилятор PHP