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

В чём разница между абстрактными классами и интерфейсами?

1.0 Junior🔥 231 комментариев
#PHP Core

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

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

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

Основное концептуальное отличие

Абстрактные классы и интерфейсы — это две основные конструкции языка PHP для реализации абстракции и полиморфизма, но они служат разным целям в архитектуре приложения.

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

Интерфейс — это полностью абстрактная конструкция, которая определяет только контракт (сигнатуры методов), который должен быть реализован классом. До PHP 8 интерфейсы могли содержать только объявления методов без реализации. С PHP 8 интерфейсы могут включать методы с реализацией по умолчанию, но основная их цель — определение обязательного поведения.

Ключевые различия

1. Наследование vs Реализация

  • Класс может наследовать только один абстрактный класс (одиночное наследование)
  • Класс может реализовывать множество интерфейсов (множественное наследование)
// Абстрактный класс - одиночное наследование
abstract class Animal {
    abstract public function makeSound();
    public function sleep() {
        return "Sleeping...";
    }
}

class Dog extends Animal {
    public function makeSound() {
        return "Woof!";
    }
}

// Интерфейсы - множественная реализация
interface CanFly {
    public function fly();
}

interface CanSwim {
    public function swim();
}

class Duck implements CanFly, CanSwim {
    public function fly() {
        return "Flying...";
    }
    public function swim() {
        return "Swimming...";
    }
}

2. Состояние (свойства)

  • Абстрактные классы могут содержать свойства с модификаторами доступа и реализовать конструктор
  • Интерфейсы до PHP 8.2 не могли содержать свойства, только константы. С PHP 8.2 интерфейсы могут объявлять свойства, но они должны быть статическими
abstract class Vehicle {
    protected string $brand;
    
    public function __construct(string $brand) {
        $this->brand = $brand;
    }
    
    abstract public function move();
}

interface Loggable {
    const LOG_LEVEL = 'INFO'; // Только константы
    
    public function log(): string;
}

3. Модификаторы доступа

  • Абстрактные классы могут использовать любые модификаторы доступа (public, protected, private)
  • Методы в интерфейсах по умолчанию публичные и не могут иметь других модификаторов

4. Конструкторы

  • Абстрактные классы могут иметь конструктор для инициализации общего состояния
  • Интерфейсы не могут иметь конструктора

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

Используйте абстрактный класс, когда:

  • Классы-наследники имеют общую логику или состояние
  • Нужен частичный шаблон реализации
  • Требуется контроль над модификаторами доступа
  • Необходим конструктор для общей инициализации
abstract class DatabaseConnection {
    protected PDO $connection;
    
    public function __construct(array $config) {
        // Общая логика подключения
        $this->connect($config);
    }
    
    abstract protected function connect(array $config): void;
    
    public function getConnection(): PDO {
        return $this->connection;
    }
}

Используйте интерфейс, когда:

  • Нужно определить контракт, который могут реализовать несвязанные классы
  • Требуется множественное наследование поведения
  • Хотите обеспечить слабую связанность между компонентами
  • Определяете роли или способности объекта
interface Authenticatable {
    public function login(): bool;
    public function logout(): void;
    public function isAuthenticated(): bool;
}

class User implements Authenticatable {
    // Реализация методов интерфейса
}

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

С выходом PHP 8 границы между интерфейсами и абстрактными классами стали менее четкими:

  1. PHP 8.0 — интерфейсы могут содержать методы с реализацией по умолчанию
  2. PHP 8.1 — добавлены final константы в интерфейсах
  3. PHP 8.2 — возможность объявлять статические свойства в интерфейсах
// PHP 8.0+ - интерфейс с реализацией по умолчанию
interface Notification {
    public function send(): bool;
    
    public function retry(int $attempts): void {
        for ($i = 0; $i < $attempts; $i++) {
            if ($this->send()) {
                break;
            }
        }
    }
}

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

  1. Принцип разделения интерфейсов (ISP) — создавайте небольшие, сфокусированные интерфейсы вместо больших монолитных
  2. Композиция над наследованием — часто лучше использовать интерфейсы с внедрением зависимостей
  3. Абстрактные классы для семейств объектов — когда классы действительно образуют иерархию "является"
  4. Интерфейсы для cross-cutting concerns — для функциональности, которая может применяться к разным типам объектов

Вывод

Основное философское различие: абстрактные классы отвечают на вопрос "что это?" (определяют сущность), а интерфейсы — на вопрос "что может делать?" (определяют поведение). В современном PHP с его постоянно развивающимися возможностями выбор между этими конструкциями часто зависит от конкретного сценария использования, требований к гибкости архитектуры и версии PHP, на которой работает приложение.