Интерфейсы и абстрактные классы в PHP
Интерфейсы и абстрактные классы в PHP: interface, implements, abstract class, контракты и когда что выбирать.
Абстрактный класс — это класс-заготовка, который нельзя создать напрямую. Интерфейс — это контракт: набор методов, которые класс обязуется реализовать. Оба инструмента помогают строить гибкую и расширяемую архитектуру.
Абстрактный класс
Абстрактный класс объявляется с ключевым словом abstract. В нём могут быть как обычные методы с реализацией, так и абстрактные — без тела. Потомок обязан реализовать все абстрактные методы:
<?php
abstract class Shape {
abstract public function area(): float; // без реализации — потомок обязан!
public function describe(): string {
return "Фигура с площадью: " . $this->area();
}
}
class Circle extends Shape {
public function __construct(private float $radius) {}
public function area(): float {
return M_PI * $this->radius ** 2;
}
}
class Rectangle extends Shape {
public function __construct(
private float $width,
private float $height,
) {}
public function area(): float {
return $this->width * $this->height;
}
}
$shapes = [new Circle(5), new Rectangle(4, 6)];
foreach ($shapes as $shape) {
echo $shape->describe() . "\n";
}
// new Shape(); // Fatal error: Cannot instantiate abstract class
Вывод:
Фигура с площадью: 78.539816339745 Фигура с площадью: 24
Интерфейс
Интерфейс — это чистый контракт без реализации. Класс «подписывается» на него через implements. Один класс может реализовывать несколько интерфейсов одновременно:
<?php
interface Drawable {
public function draw(): string;
}
interface Resizable {
public function resize(float $factor): void;
}
class Canvas implements Drawable, Resizable {
public function __construct(private float $size = 100) {}
public function draw(): string {
return "Рисую холст размером {$this->size}px";
}
public function resize(float $factor): void {
$this->size *= $factor;
}
}
$canvas = new Canvas();
echo $canvas->draw(); // Рисую холст размером 100px
$canvas->resize(1.5);
echo $canvas->draw(); // Рисую холст размером 150px
Вывод:
Рисую холст размером 100px Рисую холст размером 150px
Абстрактный класс vs Интерфейс
| Абстрактный класс | Интерфейс | |
|---|---|---|
| Реализация методов | может быть | нет (кроме default) |
| Свойства | есть | нет |
| Наследование | только одно | несколько сразу |
| Смысл | «является» (Cat — Animal) | «умеет» (Canvas — Drawable) |
Правило: если классы разделяют общий код — используйте абстрактный класс. Если нужно описать способность, которую могут иметь несвязанные классы — используйте интерфейс.
Коротко
- Абстрактный класс не создаётся через
new; его абстрактные методы обязан реализовать потомок. - Интерфейс — только контракт; класс реализует его через
implements. - Один класс может реализовывать несколько интерфейсов, но расширять только один класс.
- Абстрактный класс = общая природа, интерфейс = общая способность.