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

В объектно-ориентированном программировании классы, это не просто контейнеры для данных и логики. Это сущности с чёткими границами. Модификаторы доступа - инструмент, которым разработчик очерчивает эти границы: решает, что объект показывает миру, что передаёт потомкам и что оставляет исключительно при себе.

 

Что такое модификатор доступа

Модификатор доступа — это ключевое слово, которое ставится перед свойством или методом класса и определяет, из каких мест кода к ним можно обратиться. 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

 

Лого

Spartacus_85 [Admin]

Администратор сайта — это специалист, который отвечает за техническую поддержку и бесперебойную работу веб-ресурса.



0 Комментарий(я)

Зарегистрируйтесь чтобы оставить комментарий