Menu

Абстрактный класс PHP: абстрактные методы и применение

Абстрактный класс PHP объявляется как abstract class Name, и создать его объект нельзя: он существует, чтобы его наследовали. Он может содержать свойства, конструктор и готовые методы, а также abstract-методы без тела, которые обязан реализовать каждый дочерний класс.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Абстрактный класс PHP объявляется как abstract class Name, и создать его через new нельзя. Это база для других классов: у него могут быть свойства, конструктор и готовые методы, а также abstract-методы без тела, которые обязан реализовать каждый дочерний класс.

describe() написан один раз в Shape и вызывает area(), который предоставляет каждый дочерний класс. Абстрактный класс гарантирует, что такой метод существует, поэтому describe() может на него полагаться.

Абстрактный класс нельзя создать через new

Абстрактный класс намеренно неполон: у Shape::area() нет тела, поэтому простому объекту Shape нечего было бы выполнять. PHP отказывается его создавать и выбрасывает Error:

Абстрактные методы: правила

У абстрактного метода есть сигнатура и точка с запятой вместо тела. Каждый дочерний класс должен реализовать его с совместимой сигнатурой и той же или более широкой видимостью: метод abstract protected может стать в дочернем классе protected или public, но никогда private. Класс, в котором есть хотя бы один абстрактный метод, сам должен быть объявлен абстрактным.

Дочерний класс, который пропустил абстрактный метод, останавливает скрипт до того, как выполнится хоть что-то, если только он сам не объявлен абстрактным и не оставляет метод своим потомкам:

PHP Fatal error:  Class Square contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Shape::area) in /home/index.php on line 3

Шаблонный метод

Самая частая причина написать абстрактный класс: фиксированная последовательность шагов, где несколько шагов отличаются. Базовый класс владеет последовательностью в методе final, а дочерние заполняют шаги. Здесь один и тот же отчёт выводится обычным текстом и HTML-таблицей:

Запустите, и вкладка Page покажет HTML-таблицу над текстовой версией. У open() и close() есть тела по умолчанию, поэтому их переопределяет только HtmlReport; row() абстрактный, потому что разумного варианта по умолчанию нет. final у render() не даёт дочернему классу поменять порядок шагов.

Абстрактный класс может реализовать интерфейс

Абстрактный класс может объявить implements и оставить часть методов интерфейса своим потомкам. Это стандартный способ сочетать интерфейс (тип) с базовым классом (общий код):

Код использует подсказку типа по интерфейсу Cache, поэтому класс, который не может наследовать BaseCache (потому что уже наследует что-то другое), всё равно может реализовать Cache напрямую.

Когда использовать абстрактный класс, а когда нет

Берите абстрактный класс, когда у классов одного семейства есть настоящий общий код: свойства, конструктор, методы, одинаковые для всех. Если в базе были бы одни абстрактные методы, это замаскированный интерфейс, и интерфейс здесь лучше, потому что класс может реализовать много интерфейсов, а наследовать только один класс. Если нужно лишь поделиться несколькими вспомогательными методами между несвязанными классами, используйте трейт, а не загоняйте их под одного родителя.

Быстрая проверка перед тем, как писать abstract class: будет ли каждый дочерний класс действительно разновидностью базы (Circle это Shape)? Если честный ответ "он умеет это", а не "он один из них", пишите интерфейс.

Часто задаваемые вопросы

Что такое абстрактный класс в PHP?

Класс, объявленный как abstract class Name, объект которого нельзя создать через new. Это база для других классов: он может содержать свойства, конструктор и обычные методы и может объявлять abstract-методы, которые обязан реализовать каждый дочерний класс.

Что такое абстрактный метод в PHP?

Метод, объявленный с abstract и без тела: abstract protected function render(array $rows): string;. Класс, который его содержит, сам должен быть объявлен abstract, а каждый неабстрактный дочерний класс должен определить метод с совместимой сигнатурой.

Может ли у абстрактного класса быть конструктор в PHP?

Да. Вызвать new для абстрактного класса нельзя, но его конструктор выполняется при создании дочернего класса: автоматически (если у дочернего нет своего конструктора) или через parent::__construct(...).

Можно ли создать объект абстрактного класса в PHP?

Нет. new Shape() для абстрактного класса выбрасывает Error: Cannot instantiate abstract class Shape. Создайте объект конкретного дочернего класса, например new Circle(2).

Когда использовать абстрактный класс в PHP?

Когда у нескольких связанных классов есть настоящий общий код (свойства, конструктор, общие методы), а различаются они несколькими шагами. Поместите общий код в абстрактный класс, а различающиеся шаги объявите абстрактными. Если общего кода нет и нужен только контракт, используйте интерфейс.

Иллюстрация языков программирования Coddy

Учитесь программировать с Coddy

НАЧАТЬ