Абстрактные классы и интерфейсы — это два ключевых инструмента для реализации полиморфизма и проектирования архитектуры приложения, но они служат разным целям.
Характеристика | Абстрактный класс | Интерфейс |
---|---|---|
Экземпляр | Нельзя создать напрямую | Нельзя создать вообще |
Свойства | Может содержать свойства | Только константы |
Методы | Может содержать реализацию | Только сигнатуры методов |
Модификаторы доступа | Любые (public, protected, etc.) | Только public |
Наследование | Один класс | Множественное наследование |
Конструктор | Может иметь | Не может иметь |
Типизация | Определяет "что есть" объект | Определяет "что может" объект |
abstract class Animal {
protected $name;
public function __construct($name) {
$this->name = $name;
}
abstract public function makeSound();
public function getName() {
return $this->name;
}
}
class Dog extends Animal {
public function makeSound() {
return "Woof!";
}
}
Когда использовать:
interface Loggable {
public function log($message);
}
interface Cacheable {
public function cache($data);
}
class DataProcessor implements Loggable, Cacheable {
public function log($message) {
file_put_contents('log.txt', $message);
}
public function cache($data) {
// Реализация кэширования
}
}
Когда использовать:
Абстрактный класс — это частично реализованный класс ("is-a" отношение)
Dog
является Animal
Интерфейс — это контракт ("can-do" отношение)
DataProcessor
умеет Loggable
interface Logger {
public function log($message): void;
default public function logError(string $error): void {
$this->log("[ERROR] " . $error);
}
}
Используйте интерфейсы для:
Используйте абстрактные классы для:
Комбинируйте их:
abstract class Database implements Logger, Cacheable {
// Общая реализация для всех БД
abstract protected function connect();
public function log($message) {
// Базовая реализация
}
}
абстрактные классы предоставляют частичную реализацию и устанавливают "что есть" объект, тогда как интерфейсы определяют контракт поведения и описывают "что может" объект. В хорошей архитектуре они часто используются вместе для достижения гибкости и повторного использования кода.