Абстрактные классы
Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy — урок 25 из 91.
Абстрактный класс — это класс, экземпляр которого нельзя создать напрямую. Он служит шаблоном для других классов, определяя методы, которые должны реализовать дочерние классы. Вы создаете абстрактный класс, используя ключевое слово abstract.
<?php
abstract class Shape {
protected $color;
public function __construct($color) {
$this->color = $color;
}
abstract public function calculateArea();
public function getColor() {
return $this->color;
}
}
class Rectangle extends Shape {
private $width;
private $height;
public function __construct($color, $width, $height) {
parent::__construct($color);
$this->width = $width;
$this->height = $height;
}
public function calculateArea() {
return $this->width * $this->height;
}
}
$rect = new Rectangle("blue", 5, 3);
echo $rect->calculateArea();
Вывод:
15Класс Shape объявляет абстрактный метод calculateArea() без предоставления реализации. Любой класс, расширяющий Shape, должен реализовать этот метод. Обратите внимание, что абстрактные классы также могут содержать обычные методы, такие как getColor(), которые дочерние классы наследуют напрямую.
Абстрактные методы определяют, что должен делать дочерний класс, но не то, как он это делает. Это гарантирует, что у всех фигур будет метод calculateArea(), при этом позволяя каждой фигуре вычислять свою площадь по-разному.
Ключевой момент: Абстрактные классы сочетают в себе структуру наследования с обязательными требованиями. Используйте их, когда вы хотите разделить код между связанными классами, гарантируя при этом, что определенные методы будут реализованы каждым дочерним классом.
Задание
ЛегкоДавайте создадим систему медиаплеера, которая демонстрирует, как абстрактные классы обеспечивают соблюдение контракта, позволяя различным типам медиа реализовывать собственное поведение воспроизведения.
Вы организуете свой код в трех файлах:
Media.php— Определите абстрактный классMedia, который служит шаблоном для всех типов медиа. Он должен иметь защищенное свойство$titleи конструктор, который принимает и устанавливает заголовок. Включите абстрактный метод с именемplay(), который должны реализовать дочерние классы. Также добавьте обычный методgetTitle(), который возвращает заголовок — этот конкретный метод будет унаследован всеми дочерними классами.Song.php— Определите классSong, который расширяетMedia. Подключите файл Media в начале. Этот класс добавляет свойство$artist. Конструктор должен принимать название и исполнителя — используйтеparent::__construct()для названия, а затем сами установите исполнителя. Реализуйте обязательный методplay(), чтобы он возвращал"Playing song: [title] by [artist]".Podcast.php— Определите классPodcast, который расширяетMedia. Подключите файл Media в начале. Этот класс добавляет свойство$episode(целое число). Конструктор должен принимать название и номер эпизода — используйтеparent::__construct()для названия, а затем установите эпизод. Реализуйте обязательный методplay(), чтобы он возвращал"Playing podcast: [title] - Episode [episode]".
В main.php подключите файлы Song и Podcast. Вы получите четыре входных значения: название песни, имя исполнителя, название подкаста и номер эпизода (в виде строки для преобразования в целое число). Создайте объекты Song и Podcast с этими значениями. Выведите результат вызова play() сначала для песни, а затем для подкаста, каждый на новой строке.
Эта задача показывает, как абстрактные классы определяют контракт — каждый тип медиа должен иметь метод play(), но каждый тип реализует его по-своему. Абстрактный класс Media не может быть инстанцирован напрямую; он существует только для того, чтобы предоставить структуру и общую функциональность своим потомкам.
Шпаргалка
Абстрактный класс — это класс, экземпляр которого нельзя создать напрямую. Он служит шаблоном для других классов, определяя методы, которые должны реализовать дочерние классы. Используйте ключевое слово abstract для создания абстрактного класса.
abstract class Shape {
protected $color;
public function __construct($color) {
$this->color = $color;
}
abstract public function calculateArea();
public function getColor() {
return $this->color;
}
}Дочерние классы должны реализовать все абстрактные методы:
class Rectangle extends Shape {
private $width;
private $height;
public function __construct($color, $width, $height) {
parent::__construct($color);
$this->width = $width;
$this->height = $height;
}
public function calculateArea() {
return $this->width * $this->height;
}
}Основные характеристики:
- Абстрактные классы не могут быть инстанцированы напрямую
- Абстрактные методы не имеют реализации в абстрактном классе
- Дочерние классы должны реализовать все абстрактные методы
- Абстрактные классы могут содержать как абстрактные, так и обычные методы
- Обычные методы в абстрактных классах наследуются дочерними классами
Попробуйте сами
<?php
require_once 'Song.php';
require_once 'Podcast.php';
// Чтение входных данных
$songTitle = trim(fgets(STDIN));
$artistName = trim(fgets(STDIN));
$podcastTitle = trim(fgets(STDIN));
$episodeNumber = intval(trim(fgets(STDIN)));
// TODO: Создать объект Song с songTitle и artistName
// TODO: Создать объект Podcast с podcastTitle и episodeNumber
// TODO: Вывести результат вызова play() для песни
// TODO: Вывести результат вызова play() для подкаста
?>В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
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