Встречается на 26% собеседований по PHP

Зачем нужен абстрактный класс

Абстрактный класс в PHP — это класс, который нельзя инстанцировать напрямую; он служит шаблоном для других классов, определяя общую структуру и поведение. Он может содержать как полностью реализованные методы, так и абстрактные методы без реализации, которые обязаны реализовать все наследники. Основная цель — обеспечить единый интерфейс для группы связанных классов, избежать дублирования кода и гарантировать, что подклассы следуют заданной структуре.

Как это работает

Абстрактный класс объявляется с ключевым словом abstract. Он может содержать обычные методы с реализацией, свойства, конструкторы и абстрактные методы (объявленные с abstract без тела). Любой класс, наследующий абстрактный, обязан реализовать все абстрактные методы, иначе он сам должен быть объявлен абстрактным. Это позволяет задать обязательный контракт для наследников, одновременно предоставляя общую функциональность.

Пример

php
abstract class Животное {
    protected $имя;

    public function __construct($имя) {
        $this->имя = $имя;
    }

    public function ест() {
        echo "{$this->имя} ест";
    }

    // Абстрактный метод: подклассы обязаны реализовать
    abstract public function издаетЗвук();
}

class Собака extends Животное {
public function издаетЗвук() {
echo "{$this->имя} говорит Гав";
}
}

$мояСобака = new Собака("Бобик");
$мояСобака->ест(); // Бобик ест
$мояСобака->издаетЗвук(); // Бобик говорит Гав

text

Здесь `Животное` — абстрактный класс: он определяет общий метод `ест()` и требует от наследников реализовать `издаетЗвук()`. Класс `Собака` реализует этот метод, поэтому его можно инстанцировать. Попытка создать объект `Животное` вызовет ошибку.

## Зачем нужны абстрактные классы

- **Единый интерфейс**: Абстрактный класс задаёт общий набор методов, что упрощает работу с разными наследниками через базовый тип. Например, можно написать функцию, принимающую `Животное`, и она будет работать с любой его реализацией.
- **Избежание дублирования**: Общая логика (например, конструктор, метод `ест()`) выносится в абстрактный класс, и каждый подкласс не повторяет её.
- **Контроль наследования**: Запрет на создание экземпляров абстрактного класса гарантирует, что используются только конкретные реализации. Абстрактные методы вынуждают подклассы предоставлять собственную реализацию, обеспечивая наличие необходимого поведения.
- **Гибкость**: Можно комбинировать готовые методы с абстрактными, позволяя подклассам переопределять или дополнять поведение, сохраняя обязательные части.
- **Расширяемость**: Добавление нового подкласса не требует изменения существующего кода, работающего с абстрактным классом, что облегчает расширение системы.

## Подводные камни

- **Нельзя создать экземпляр**: Попытка `new Животное()` приведёт к фатальной ошибке. Это важно помнить при проектировании.
- **Обязательная реализация**: Если подкласс не реализует все абстрактные методы, он сам должен быть абстрактным. Иначе возникнет ошибка.
- **Одиночное наследование**: В PHP класс может наследовать только один класс, поэтому абстрактный класс не решает проблему множественного наследования. Для этого используются интерфейсы и трейты.
- **Перегрузка методов**: Абстрактные методы не могут быть `private` — они должны быть `public` или `protected`, чтобы наследники могли их реализовать.

## Когда использовать

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

## Коротко

- Абстрактный класс — это шаблон для наследников, который нельзя инстанцировать.
- Он содержит обычные методы (общая логика) и абстрактные методы (обязательные для реализации).
- Используется для единого интерфейса, избежания дублирования и контроля структуры подклассов.
- В PHP класс наследует только один абстрактный класс; для множественного контракта используйте интерфейсы.
как отвечать на вопрос
пример собеседования
фреймворки на собеседовании
типичные вопросы junior
интервью вопросы и ответы