В объектно-ориентированном программировании классы, это не просто контейнеры для данных и логики. Это сущности с чёткими границами. Модификаторы доступа - инструмент, которым разработчик очерчивает эти границы: решает, что объект показывает миру, что передаёт потомкам и что оставляет исключительно при себе.
Что такое модификатор доступа
Модификатор доступа — это ключевое слово, которое ставится перед свойством или методом класса и определяет, из каких мест кода к ним можно обратиться. PHP поддерживает три модификатора: public, protected и private. Вместе они реализуют принцип инкапсуляции - один из трёх фундаментальных принципов ООП.
Инкапсуляция означает, что объект сам управляет своим состоянием. Внешний код не должен иметь возможности произвольно менять внутренние данные объекта в обход его логики. Модификаторы доступа, это и есть механизм такого управления.
Наглядный пример: банковский счёт
Разберём модификаторы на классе BankAccount. Это удобная модель, потому что у банковского счёта есть данные, которые нельзя менять произвольно (баланс), данные для внутренней логики (история операций) и публичный интерфейс для взаимодействия (методы пополнения и снятия).
class BankAccount
{
// public: номер счёта читают все — банк, клиент, система
public readonly string $number;
// protected: баланс доступен наследникам (например, SavingsAccount)
protected float $balance;
// private: история операций — внутреннее дело этого класса
private array $transactions = [];
public function __construct(string $number, float $initialBalance = 0.0)
{
$this->number = $number;
$this->balance = $initialBalance;
}
// public: основной интерфейс взаимодействия
public function deposit(float $amount): void
{
$this->validateAmount($amount);
$this->balance += $amount;
$this->recordTransaction('deposit', $amount);
}
public function withdraw(float $amount): void
{
$this->validateAmount($amount);
if ($amount > $this->balance) {
throw new \RuntimeException('Недостаточно средств');
}
$this->balance -= $amount;
$this->recordTransaction('withdraw', $amount);
}
public function getBalance(): float
{
return $this->balance;
}
// private: вспомогательные методы — детали реализации
private function validateAmount(float $amount): void
{
if ($amount <= 0) {
throw new \InvalidArgumentException('Сумма должна быть положительной');
}
}
private function recordTransaction(string $type, float $amount): void
{
$this->transactions[] = [
'type' => $type,
'amount' => $amount,
'at' => date('Y-m-d H:i:s'),
];
}
}
Применение.
$account = new BankAccount('RU-0042', 5000.0);
// public — доступно везде
echo $account->number; // RU-0042
$account->deposit(1000);
echo $account->getBalance(); // 6000
// protected — закрыто снаружи класса
echo $account->balance;
// Fatal error: Cannot access protected property
// private — закрыто снаружи
$account->transactions;
// Fatal error: Cannot access private property
// readonly — нельзя переписать после инициализации
$account->number = 'RU-9999';
// Fatal error: Cannot modify readonly property
Модификатор protected в наследовании
Разница между private и protected проявляется именно при наследовании. Всё, что помечено как private, невидимо даже для дочерних классов. protected открывает доступ потомкам, не открывая его всему внешнему миру.
class SavingsAccount extends BankAccount
{
private float $interestRate;
public function __construct(string $number, float $balance, float $rate)
{
parent::__construct($number, $balance);
$this->interestRate = $rate;
}
public function accrueInterest(): void
{
// protected $balance доступен в наследнике
$interest = $this->balance * $this->interestRate;
$this->balance += $interest;
echo "Начислено процентов: {$interest} ₽\n";
// private $transactions недоступен — только у родителя
// $this->transactions[] = [...]; — Fatal error
}
}
$savings = new SavingsAccount('RU-0099', 10000.0, 0.05);
$savings->accrueInterest(); // Начислено процентов: 500 ₽
echo $savings->getBalance(); // 10500
readonly — дополнение к модификаторам в PHP 8
PHP 8.1 ввёл ключевое слово readonly, которое работает совместно с модификаторами доступа. Оно не заменяет их, а добавляет дополнительное ограничение: свойство можно задать только один раз, после чего оно становится неизменяемым. Это мощный инструмент для создания объектов-значений (Value Objects), у которых состояние не меняется после создания.
class Money
{
// public readonly: читать могут все, записать — никто (после __construct)
public function __construct(
public readonly float $amount,
public readonly string $currency
) {}
public function add(Money $other): static
{
if ($this->currency !== $other->currency) {
throw new \LogicException('Разные валюты');
}
// Создаём новый объект — не меняем текущий
return new static($this->amount + $other->amount, $this->currency);
}
public function format(): string
{
return number_format($this->amount, 2) . ' ' . $this->currency;
}
}
$price = new Money(1500.0, 'RUB');
$shipping = new Money(250.0, 'RUB');
$total = $price->add($shipping);
echo $total->format(); // 1 750.00 RUB
// Изменить нельзя — readonly защищает
$price->amount = 0;
// Fatal error: Cannot modify readonly property Money::$amount
0 Комментарий(я)
Зарегистрируйтесь чтобы оставить комментарий