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

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

2.2 Middle🔥 231 комментариев
#ООП

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

🐱
claude-haiku-4.5PrepBro AI21 мар. 2026 г.(ред.)

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

# Разница между интерфейсом и абстрактным классом

Это классический вопрос в ООП, и в PHP эта разница достаточно ясна. Рассмотрим оба подхода.

Интерфейс (Interface)

Интерфейс - это контракт, определяющий какие методы должны быть реализованы, но БЕЗ реализации самих методов:

interface PaymentInterface {
    public function pay(float $amount): bool;
    public function refund(float $amount): bool;
    public function getTransactionId(): string;
}

Характеристики:

  • Только public методы (PHP 8.1+)
  • Нет реализации (только сигнатуры)
  • Нет свойств (только константы)
  • Класс может реализовать множество интерфейсов (implements A, B, C)
  • Фокус на КОНТРАКТЕ, а не на реализации

Абстрактный класс (Abstract Class)

Абстрактный класс - это частично реализованный класс, который нельзя инстанцировать напрямую:

abstract class PaymentProvider {
    protected string $apiKey;
    
    public function __construct(string $apiKey) {
        $this->apiKey = $apiKey;
    }
    
    abstract public function pay(float $amount): bool;
    
    // Конкретная реализация
    public function getBalance(): float {
        return $this->fetchBalance();
    }
    
    protected function fetchBalance(): float {
        // Реализация
        return 1000.0;
    }
}

Характеристики:

  • Может иметь как абстрактные методы, так и конкретные реализации
  • Может иметь свойства (protected, private)
  • Может иметь конструктор и другую инициализацию
  • Класс может наследовать только ОДИН абстрактный класс (extends)
  • Фокус на ПОВТОРНОМ ИСПОЛЬЗОВАНИИ КОДА

Основные различия в таблице

КритерийИнтерфейсАбстрактный класс
Инстанцирование❌ Нельзя❌ Нельзя
МетодыТолько сигнатурыМогут быть реализованы
Свойства❌ Нет✅ Да (public/protected/private)
Конструктор❌ Нет✅ Да
Множественное наследование✅ Да (implements A, B, C)❌ Нет (extends X только)
Модификаторы доступа методовТолько publicpublic/protected/private
Константы✅ Да✅ Да

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

Используй ИНТЕРФЕЙС когда:

// Хочешь определить контракт поведения для разных типов
interface NotificationInterface {
    public function send(string $message): bool;
}

class EmailNotification implements NotificationInterface {
    public function send(string $message): bool {
        // Email отправка
        return true;
    }
}

class SMSNotification implements NotificationInterface {
    public function send(string $message): bool {
        // SMS отправка
        return true;
    }
}

class SlackNotification implements NotificationInterface {
    public function send(string $message): bool {
        // Slack отправка
        return true;
    }
}

// В коде работаешь с интерфейсом
function notifyUser(NotificationInterface $notifier, string $msg) {
    $notifier->send($msg);
}
  • Разные реализации одного поведения
  • Dependency Injection и Loose Coupling
  • Тестирование (мокирование интерфейса)
  • SOLID - Interface Segregation Principle

Используй АБСТРАКТНЫЙ КЛАСС когда:

// Есть общий код и логика для группы связанных классов
abstract class Repository {
    protected PDO $db;
    
    public function __construct(PDO $db) {
        $this->db = $db;
    }
    
    // Общий код для всех репозиториев
    public function findById(int $id): ?array {
        $stmt = $this->db->prepare('SELECT * FROM ' . $this->table() . ' WHERE id = ?');
        $stmt->execute([$id]);
        return $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
    }
    
    // Абстрактный метод - каждый репозиторий сам решает
    abstract protected function table(): string;
}

class UserRepository extends Repository {
    protected function table(): string {
        return 'users';
    }
    
    public function findByEmail(string $email): ?array {
        $stmt = $this->db->prepare('SELECT * FROM users WHERE email = ?');
        $stmt->execute([$email]);
        return $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
    }
}
  • Общее функционал для иерархии классов
  • Государство и инициализация (конструктор)
  • Переиспользование кода через наследование
  • Template Method паттерн

Best Practice в современных проектах

В PHP рекомендуется:

  1. Программировать на интерфейсах - это делает код более гибким
  2. Минимизировать глубину наследования - лучше композиция
  3. Использовать Dependency Injection - работа через интерфейсы
  4. Абстрактные классы для реальных иерархий - когда есть по-настоящему общий код
// Хороший пример архитектуры
interface UserServiceInterface {
    public function register(string $email, string $password): User;
    public function login(string $email, string $password): ?User;
}

class UserService implements UserServiceInterface {
    public function __construct(
        private UserRepository $userRepository,
        private PasswordHasher $hasher
    ) {}
    
    public function register(string $email, string $password): User {
        // Реализация
    }
}

Это позволяет легко тестировать, мокировать и менять реализацию без изменения интерфейса.

В чем разница между интерфейса от абстрактного класса? | PrepBro