Ответ
Да, начиная с PHP 8.1, интерфейсы могут содержать статические методы. Это позволяет определить общий статический контракт для всех реализующих классов.
Пример:
interface Logger {
public static function create(string $name): self;
public function log(string $message): void;
}
class FileLogger implements Logger {
private string $name;
private function __construct(string $name) {
$this->name = $name;
}
public static function create(string $name): self {
return new self($name);
}
public function log(string $message): void {
file_put_contents($this->name . '.log', $message . PHP_EOL, FILE_APPEND);
}
}
// Использование
$logger = FileLogger::create('app');
$logger->log('Запуск системы');
Ключевые моменты:
- Статические методы в интерфейсах должны быть объявлены как
public. - Они не могут быть абстрактными (должны иметь тело, даже если это просто
{}в интерфейсе). - Класс, реализующий интерфейс, должен предоставить метод с точно такой же сигнатурой.
- До PHP 8.1 объявление статического метода в интерфейсе вызывало фатальную ошибку.
Ответ 18+ 🔞
А, ну вот это поворот, ёпта! Раньше-то в интерфейсах статику запихнуть было нельзя, аж до версии 8.1. А теперь — пожалуйста, нате вам. Теперь можно в интерфейсе прописать, что все, кто его реализует, обязаны иметь какой-то конкретный статический метод. Удобно, если вам нужен единый фабричный метод create() для всех логгеров или чего-то такого.
Смотри, как это выглядит:
interface Logger {
public static function create(string $name): self;
public function log(string $message): void;
}
class FileLogger implements Logger {
private string $name;
private function __construct(string $name) {
$this->name = $name;
}
public static function create(string $name): self {
return new self($name);
}
public function log(string $message): void {
file_put_contents($this->name . '.log', $message . PHP_EOL, FILE_APPEND);
}
}
// Использование
$logger = FileLogger::create('app');
$logger->log('Запуск системы');
А теперь главное, что надо запомнить, а то накосячишь:
- Эти статические методы в интерфейсе обязательно должны быть
public. Никакихprivate staticтам не завезли, и слава богу, а то был бы пиздопроебибна. - Они не могут быть абстрактными, им прямо в интерфейсе нужно тело писать. Пусть даже пустое —
{}, но писать. - Класс, который этот интерфейс подписывает, обязан этот статик метод реализовать, причём с точно такой же сигнатурой. Иначе — сам от себя охуеешь, когда компилятор тебе в рыло ошибку вывалит.
- И да, главное — раньше, до 8.1, если бы ты попробовал так сделать, PHP бы тебе просто сказал «иди ты нахуй» фатальной ошибкой. А теперь — можно. Прогресс, блядь, налицо.