Ответ
Основное отличие — статическое замыкание не имеет доступа к псевдопеременной $this и не захватывает контекст объекта, в котором оно было объявлено. Ключевое слово static перед function накладывает это ограничение.
Обычное замыкание автоматически захватывает $this, если объявлено в контексте метода объекта:
class Logger {
private string $prefix = 'LOG:';
public function getClosure(): Closure {
// Обычное замыкание ЗАХВАТЫВАЕТ $this
return function ($message) {
// Имеет доступ к private-свойству $this->prefix
echo $this->prefix . ' ' . $message;
};
}
}
$logger = new Logger();
$closure = $logger->getClosure();
$closure('Test'); // Вывод: LOG: Test
Статическое замыкание не может использовать $this, даже если создано внутри метода:
class Logger {
private string $prefix = 'LOG:';
public function getStaticClosure(): Closure {
$prefix = $this->prefix; // Нужно явно захватить значение
// Статическое замыкание НЕ ЗАХВАТЫВАЕТ $this
return static function ($message) use ($prefix) {
// echo $this->prefix; // ФАТАЛЬНАЯ ОШИБКА: Using $this when not in object context
echo $prefix . ' ' . $message; // Работает, т.к. $prefix захвачена явно
};
}
}
Зачем это нужно?
- Явное указание намерений: Код показывает, что замыкание не зависит от состояния объекта.
- Предотвращение утечек памяти: Поскольку нет ссылки на порождающий объект (
$this), этот объект может быть удалён сборщиком мусора, даже если замыкание ещё существует. В обычном замыкании объект будет жить, пока живо замыкание. - Использование в статическом контексте: Статические замыкания можно безопасно использовать в статических методах или там, где контекст объекта не определён.
- Оптимизация: Небольшой выигрыш в производительности, так как не требуется обработка контекста объекта.
Вывод: Используйте static closure, когда ваша анонимная функция является чистой (не зависит от состояния объекта) или должна пережить объект, в котором создана.