Инкапсуляция и видимость в PHP

Инкапсуляция в PHP: модификаторы public, private, protected, геттеры и сеттеры, readonly-свойства в PHP 8.1.

Инкапсуляция — принцип ООП, при котором данные объекта скрыты от внешнего кода. Доступ к ним предоставляется только через специальные методы. Это защищает объект от случайных ошибок.

Модификаторы доступа

PHP предоставляет три уровня видимости для свойств и методов:

МодификаторКто видит
publicвсе — класс, потомки, внешний код
protectedкласс и его потомки
privateтолько сам класс
<?php
class BankAccount {
    private float $balance;       // снаружи недоступен

    public function __construct(float $initial) {
        $this->balance = $initial;
    }

    public function deposit(float $amount): void {
        if ($amount <= 0) {
            throw new \InvalidArgumentException("Сумма должна быть положительной");
        }
        $this->balance += $amount;
    }

    public function getBalance(): float {
        return $this->balance;
    }
}

$account = new BankAccount(1000);
$account->deposit(500);
echo $account->getBalance(); // Вывод: 1500

// $account->balance = 9999999; // Fatal error: Cannot access private property

Вывод:

1500

Теперь баланс нельзя изменить напрямую — только через метод deposit(), который проверяет корректность суммы.

Геттеры и сеттеры

Геттер (getter) возвращает значение приватного свойства, сеттер (setter) — устанавливает его с проверкой:

<?php
class User {
    private string $name;
    private int $age;

    public function __construct(string $name, int $age) {
        $this->setName($name);
        $this->setAge($age);
    }

    public function getName(): string { return $this->name; }

    public function setName(string $name): void {
        if (mb_strlen(trim($name)) < 2) {
            throw new \InvalidArgumentException("Имя слишком короткое");
        }
        $this->name = trim($name);
    }

    public function getAge(): int { return $this->age; }

    public function setAge(int $age): void {
        if ($age < 0 || $age > 150) {
            throw new \InvalidArgumentException("Некорректный возраст");
        }
        $this->age = $age;
    }
}

$user = new User("Анна", 25);
echo $user->getName(); // Вывод: Анна
$user->setAge(26);
echo $user->getAge();  // Вывод: 26

Вывод:

Анна
26

readonly-свойства (PHP 8.1)

readonly — свойство, которое можно задать только один раз (обычно в конструкторе). После этого изменить его нельзя. Идеально для идентификаторов и неизменных данных:

<?php
class Order {
    public function __construct(
        public readonly int $id,
        public readonly string $createdAt,
    ) {}
}

$order = new Order(id: 42, createdAt: "2024-01-15");
echo $order->id;        // Вывод: 42
echo $order->createdAt; // Вывод: 2024-01-15

// $order->id = 99; // Error: Cannot modify readonly property

Вывод:

42
2024-01-15

Правило: делайте свойства private по умолчанию. Открывайте доступ явно только там, где это необходимо.

Коротко

  • Инкапсуляция — скрытие данных. Свойства делаем private, предоставляем геттеры и сеттеры.
  • public — для всех; protected — для класса и потомков; private — только внутри класса.
  • Сеттеры позволяют проверять данные перед записью — это защищает объект от некорректного состояния.
  • readonly (PHP 8.1) — свойство, которое записывается только один раз.
Проверьте себя
1. Свойство объявлено как private. Из каких мест к нему можно обратиться?
AТолько из самого класса
BИз класса и всех его потомков
CИз любого места программы
DИз класса и классов в том же файле
2. Зачем использовать сеттер вместо прямого присваивания свойству?
AСеттеры работают быстрее прямого присваивания
BСеттер позволяет проверить значение перед записью и защитить объект
CPHP требует сеттеры для всех свойств
DСеттеры нужны только в абстрактных классах
3. Что означает readonly-свойство в PHP 8.1?
AСвойство доступно только для чтения извне (записывать можно через сеттер)
BСвойство можно задать только один раз — обычно в конструкторе
CСвойство хранится только в памяти и не сохраняется в БД
DСвойство автоматически становится public
Поддержать проект