Чем отличается абстрактный класс от интерфейса
Абстрактный класс и интерфейс — это два способа определить контракт для классов в PHP, но они имеют разные цели и ограничения. Абстрактный класс может содержать реализацию методов и свойства, а интерфейс — только сигнатуры методов (без реализации) и не может содержать свойства. Класс может наследовать только один абстрактный класс, но может реализовывать множество интерфейсов.
Основные различия
| Критерий | Абстрактный класс | Интерфейс |
|---|---|---|
| Ключевое слово | abstract class | interface |
| Свойства | Может иметь свойства (включая константы) | Не может иметь свойства (только константы) |
| Методы | Может содержать как абстрактные (без тела), так и обычные методы с реализацией | Все методы должны быть абстрактными (без тела) |
| Наследование | Класс может наследовать только один абстрактный класс | Класс может реализовывать несколько интерфейсов |
| Модификаторы доступа | Методы могут быть public, protected, private | Все методы должны быть public |
Как это работает
Абстрактный класс объявляется с ключевым словом abstract. Он может содержать абстрактные методы (без тела) и обычные методы с реализацией. Абстрактные методы обязаны быть реализованы в дочерних классах. Например:
abstract class Car {
protected string $brand;
abstract public function startEngine(): void;
public function getBrand(): string {
return $this->brand;
}
}Интерфейс объявляется с ключевым словом interface. Он определяет только сигнатуры методов, которые должны быть реализованы в классе. Интерфейс не может содержать свойства, но может содержать константы. Например:
interface Drivable {
public function drive(): void;
public function stop(): void;
}Класс может реализовать несколько интерфейсов, перечисляя их через запятую:
class Bicycle implements Drivable, EcoFriendly {
public function drive(): void {
// реализация
}
public function stop(): void {
// реализация
}
}Когда использовать
Абстрактный класс подходит, когда у группы классов есть общая реализация (например, общие свойства или методы), которую можно вынести в базовый класс. Он также позволяет задать общий шаблон для иерархии классов. Например, абстрактный класс Car может содержать общую логику для всех автомобилей, а конкретные классы Ford и Toyota наследуют её и добавляют свои особенности.
Интерфейс следует использовать, когда нужно определить контракт для классов, которые могут быть совершенно разными по своей природе, но должны поддерживать определённое поведение. Например, интерфейс Drivable может быть реализован и автомобилем, и велосипедом, хотя у них нет общей реализации.
Подводные камни
- Нельзя создать экземпляр ни абстрактного класса, ни интерфейса.
- Если класс наследует абстрактный класс, он должен реализовать все абстрактные методы, иначе класс тоже должен быть объявлен абстрактным.
- Если класс реализует интерфейс, он должен реализовать все методы интерфейса, иначе класс должен быть объявлен абстрактным.
- В PHP интерфейсы могут наследовать другие интерфейсы, но не классы.
- Абстрактные классы могут реализовывать интерфейсы, но это не обязательно.
Коротко
- Абстрактный класс — это частично реализованный класс: может иметь свойства и методы с телом.
- Интерфейс — это чистый контракт: только сигнатуры методов, без свойств и реализации.
- Класс наследует один абстрактный класс, но реализует много интерфейсов.
- Выбирайте абстрактный класс для общей логики, интерфейс — для общего поведения.
