← Назад к вопросам

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

1.8 Middle🔥 111 комментариев
#PHP Core

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Когда выбирать абстрактные классы в PHP

Выбор абстрактных классов обусловлен архитектурными задачами и шаблонами проектирования. Абстрактные классы идеально подходят для создания каркаса (скелета) семейств связанных классов, предоставляя частичную реализацию и навязывая контракт для производных классов.

Ключевые сценарии применения

1. Наличие общей реализации

Когда несколько классов разделяют общую логику, но также имеют уникальные особенности. Абстрактный класс позволяет инкапсулировать общий код, избегая дублирования.

abstract class AbstractPaymentGateway {
    protected $apiKey;
    
    public function __construct(string $apiKey) {
        $this->apiKey = $apiKey;
    }
    
    // Общая реализация
    protected function logTransaction(array $data): void {
        // Логирование в БД или файл
    }
    
    // Абстрактные методы для реализации в потомках
    abstract public function processPayment(float $amount): bool;
    abstract public function refund(string $transactionId): bool;
}

class StripeGateway extends AbstractPaymentGateway {
    public function processPayment(float $amount): bool {
        $this->logTransaction(['amount' => $amount]);
        // Уникальная логика Stripe
        return true;
    }
    
    public function refund(string $transactionId): bool {
        // Уникальная логика возврата Stripe
        return true;
    }
}

2. Обеспечение контракта с частичной реализацией

Когда нужно гарантировать наличие определенных методов у всех наследников, но при этом предоставить готовую базу. Это более гибко, чем интерфейсы, которые не содержат реализации.

3. Шаблон "Шаблонный метод" (Template Method)

Классический паттерн, где абстрактный класс определяет скелет алгоритма, оставляя детали реализации подклассам.

abstract class DataProcessor {
    // Шаблонный метод - определяет структуру
    final public function process(string $input): array {
        $data = $this->decode($input);
        $validated = $this->validate($data);
        return $this->transform($validated);
    }
    
    protected function decode(string $input): array {
        return json_decode($input, true);
    }
    
    abstract protected function validate(array $data): array;
    abstract protected function transform(array $data): array;
}

Сравнение с интерфейсами

Важно понимать ключевые отличия:

  • Интерфейсы определяют только контракт (сигнатуры методов)
  • Абстрактные классы могут содержать реализацию, свойства, константы
  • Класс может реализовывать несколько интерфейсов, но наследовать только один абстрактный класс

Практические рекомендации

  1. Создание иерархий объектов с четким отношением "is-a" (является). Например, VehicleCarElectricCar.

  2. Контроль состояния через protected свойства с общей инициализацией в конструкторе абстрактного класса.

  3. Предоставление утилитных методов, полезных для всех наследников, но не предназначенных для публичного использования.

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

  • Когда нужна множественная "наследуемость" поведения - лучше использовать интерфейсы с трейтами (traits)
  • Для легковесных контрактов без общей реализации
  • Когда иерархия может измениться - композиция часто предпочтительнее наследования

Эволюция в современных PHP

С появлением PHP 8.0+ и возможностей интерфейсов (константы, абстрактные private методы в трейтах), границы между абстрактными классами и интерфейсами несколько стерлись. Однако абстрактные классы остаются предпочтительным выбором, когда:

  • Есть значительный объем общей логики
  • Требуется контроль над конструктором и инициализацией
  • Нужно инкапсулировать состояние (свойства с модификаторами доступа)

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

Когда нужно выбирать абстрактные классы? | PrepBro