Анонимные классы
Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy — урок 58 из 91.
Иногда вам нужен простой, разовый объект без лишних затрат на определение полноценного класса. Анонимные классы позволяют создавать объекты «на лету», именно там, где они вам нужны. Они особенно полезны в сочетании с внедрением зависимостей.
Анонимный класс определяется с помощью new class, за которым следует тело класса:
<?php
$logger = new class {
public function log(string $message): void {
echo "Log: $message";
}
};
$logger->log("Hello!");
Вывод:
Log: Hello!Анонимные классы становятся мощным инструментом при реализации интерфейсов. Это идеально подходит для тестирования или когда вам нужна быстрая реализация без загромождения кодовой базы классами одноразового использования:
<?php
interface Notifier {
public function send(string $message): string;
}
function notify(Notifier $notifier, string $msg): string {
return $notifier->send($msg);
}
$result = notify(new class implements Notifier {
public function send(string $message): string {
return "Sent: $message";
}
}, "Test message");
echo $result;
Вывод:
Sent: Test messageАнонимные классы также могут расширять другие классы, использовать трейты и принимать аргументы конструктора. Они имеют полный доступ к возможностям ООП — они просто определяются по месту (inline), а не в отдельном файле. Используйте их, когда полное определение класса было бы избыточным, но вам все равно требуется объектно-ориентированное поведение.
Задание
ЛегкоДавайте создадим систему форматирования данных, которая демонстрирует мощь анонимных классов. Вместо создания отдельных файлов классов для простых одноразовых реализаций, вы будете использовать анонимные классы для создания быстрых реализаций прямо там, где они вам нужны.
Вы организуете свой код в двух файлах:
FormatterInterface.php— Определите интерфейс с именемFormatterInterfaceс единственным методомformat(string $data): string. Это устанавливает контракт, которому должен следовать любой форматер.main.php— Подключите файл интерфейса и создайте классDataProcessor, который использует внедрение зависимостей для принятия любого форматера. Класс должен:- Принимать
FormatterInterfaceв своем конструкторе - Иметь метод
process(string $data), который делегирует работу внедренному форматеру и возвращает его результат
Вы получите два входных значения: тип формата (
"upper"или"reverse") и строку для форматирования.В зависимости от типа формата создайте анонимный класс, реализующий
FormatterInterface:- Для
"upper": методformat()должен возвращать данные, преобразованные в верхний регистр - Для
"reverse": методformat()должен возвращать перевернутые данные
Внедрите ваш анонимный класс в
DataProcessor, вызовитеprocess()с входной строкой и выведите результат.- Принимать
Этот подход идеально подходит, когда вам нужна быстрая реализация без загромождения кодовой базы файлами классов одноразового использования. Анонимный класс создается по месту (inline), реализует требуемый интерфейс и может быть передан куда угодно, где ожидается этот интерфейс.
Шпаргалка
Анонимные классы позволяют создавать объекты «на лету» без определения полноценного класса. Они определяются с помощью new class, за которым следует тело класса:
<?php
$logger = new class {
public function log(string $message): void {
echo "Log: $message";
}
};
$logger->log("Hello!");
Анонимные классы могут реализовывать интерфейсы, что делает их полезными для внедрения зависимостей и тестирования:
<?php
interface Notifier {
public function send(string $message): string;
}
function notify(Notifier $notifier, string $msg): string {
return $notifier->send($msg);
}
$result = notify(new class implements Notifier {
public function send(string $message): string {
return "Sent: $message";
}
}, "Test message");
Анонимные классы поддерживают все возможности ООП: они могут расширять другие классы, использовать трейты и принимать аргументы конструктора. Используйте их, когда определение полноценного класса было бы избыточным, но вам все равно требуется объектно-ориентированное поведение.
Попробуйте сами
<?php
require_once 'FormatterInterface.php';
// TODO: Создайте класс DataProcessor, который:
// - Принимает FormatterInterface в своем конструкторе
// - Имеет метод process(string $data), который делегирует выполнение форматировщику
// Чтение входных данных
$formatType = trim(fgets(STDIN));
$inputString = trim(fgets(STDIN));
// TODO: На основе $formatType ("upper" или "reverse") создайте анонимный класс,
// который реализует FormatterInterface
// - Для "upper": format() должен возвращать версию данных в верхнем регистре
// - Для "reverse": format() должен возвращать перевернутую версию данных
// TODO: Создайте DataProcessor с вашим анонимным классом форматировщика
// Вызовите process() с входной строкой и выведите результат
?>В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово $thisМетодыСвойстваКонструктор (__construct)Деструктор (__destruct)Итоги — Простой калькулятор4Наследование
Основы наследованияКлючевое слово parent::Переопределение методовКлючевое слово finalАбстрактные классыИтоги — Иерархия сотрудников7Инкапсуляция
Public, Protected, PrivateПодробный разбор модификаторов доступаГеттеры и сеттерыСокрытие данныхConstructor Promotion (8.0)Итоги — Система учета студентов10Продвинутые концепции ООП
Композиция против наследованияВнедрение зависимостейАнонимные классыПеречисления (PHP 8.1)Файберы (PHP 8.1)Глубокое погружение в клонирование объектовГенераторы и итераторы13Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий2Пространства имен и автозагрузка
Введение в пространства именКлючевое слово useСтандарт автозагрузки PSR-4Автозагрузчик ComposerИтоги: структурированный проект5Интерфейсы и контракты
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовИнтерфейс против абстрактного классаType Hinting с интерфейсамиИтоги — Калькулятор фигур8Магические методы
Введение в магические методы__toString и __debugInfo__get, __set, __isset, __unset__call и __callStatic__clone и клонирование объектов__serialize и __unserializeИтоги — Кастомная коллекция11Система типов и обработка ошибок
Объявление типовNullable-типыТипы объединения и пересеченияКлассы исключенийИерархия пользовательских исключенийTry, Catch, FinallyИтоги — Валидатор форм14Проект: Управление библиотекой
Обзор проектаКлассы Book и User3Свойства классов
Свойства экземпляра и статические свойстваКонстанты в классахСтатические методы и свойстваПриватные и защищенные свойстваСвойства Readonly (PHP 8.1)Итоги — Менеджер банковского счета6Полиморфизм
Снова о переопределении методовПолиморфизм через интерфейсыType Hinting и Union TypesПозднее статическое связываниеИтоги — Payment Processor9Трейты
Введение в трейтыИспользование нескольких трейтовРазрешение конфликтов трейтовАбстрактные методы в трейтахТрейты и наследование12Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн Strategy