📘 Глава 21. Статические свойства и методы, `self`, `static`, абстрактные и финальные классы
📌 Статические свойства и методы
Иногда удобно обращаться к свойствам или методам класса без создания его экземпляра. Для этого используются статические (static
) члены класса.
🧪 Пример статического метода
class MathHelper {
public static function square(int $x): int {
return $x * $x;
}
}
echo MathHelper::square(5); // 25
-
Метод
square
можно вызывать безnew MathHelper()
-
Полезно для утилит, хелперов, констант и фабрик
🗃 Пример статического свойства
class Config {
public static string $appName = "MyApp";
}
echo Config::$appName; // MyApp
🔄 Отличие self
и static
class Base {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who();
}
}
class Child extends Base {
public static function who() {
echo __CLASS__;
}
}
Child::test(); // Child (а не Base!)
-
self::
— жёсткая ссылка на текущий класс, где объявлен метод -
static::
— позднее статическое связывание (late static binding), позволяет учитывать наследование
🧱 Абстрактные классы
Абстрактный класс — это шаблон, который не может быть создан напрямую. В нём могут быть как реализованные, так и абстрактные (незаконченные) методы.
✏️ Пример
abstract class Shape {
abstract public function area(): float;
public function say() {
echo "I'm a shape!";
}
}
class Square extends Shape {
public function __construct(private float $side) {}
public function area(): float {
return $this->side * $this->side;
}
}
-
Метод
area
обязателен для реализации в наследнике -
Можно использовать абстрактные классы как универсальный интерфейс + частичная реализация
🔒 Финальные классы и методы
🚫 final class
final class Core {
// ...
}
- Нельзя унаследовать
Core
🚫 final function
class A {
final public function log() {
echo "Logging...";
}
}
class B extends A {
// public function log() {} ❌ Ошибка!
}
- Метод
log
нельзя переопределить в потомках
🧰 Где использовать?
-
static
— утилиты, глобальные флаги, конфиги, фабрики, кеш -
self::
— если точно знаешь, что метод/свойство из текущего класса -
static::
— когда хочешь использовать динамическое поведение в наследниках -
abstract
— для создания универсальных основ -
final
— защита от нежелательного наследования и переопределения
💡 Пример: простой регистратор логов
class Logger {
protected static array $logs = [];
public static function log(string $msg): void {
self::$logs[] = $msg;
}
public static function all(): array {
return self::$logs;
}
}
Logger::log("Started app");
Logger::log("DB connected");
print_r(Logger::all());
✅ Что ты усвоил:
-
Как и зачем использовать
static
,self
,static::
-
Что такое абстрактные и финальные классы
-
Принципы построения удобных и безопасных архитектур
⏭ В следующей главе:
Перейдём к интерфейсам, множественному программному контракту, dependency injection, и SOLID-принципам — это фундамент чистого и масштабируемого кода.