Public, Protected, Private
Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy — урок 38 из 91.
Добро пожаловать в главу об инкапсуляции! Инкапсуляция — это контроль доступа к внутренним данным вашего класса. PHP предоставляет три модификатора доступа, которые определяют, откуда можно получить доступ к свойствам и методам: public, protected и private.
Вот как работает каждый модификатор:
<?php
class BankAccount {
public $accountHolder; // Доступно отовсюду
protected $accountNumber; // Доступно в этом классе и дочерних классах
private $balance; // Доступно только в этом классе
public function __construct($holder, $number, $balance) {
$this->accountHolder = $holder;
$this->accountNumber = $number;
$this->balance = $balance;
}
public function getBalance() {
return $this->balance;
}
}
$account = new BankAccount("John", "12345", 1000);
echo $account->accountHolder . "\n"; // Работает - public
echo $account->getBalance(); // Работает - публичный метод
Вывод:
John
1000Попытка доступа к $account->balance напрямую вызовет ошибку, так как это свойство является закрытым (private). То же самое относится к $account->accountNumber извне иерархии классов. Эта защита гарантирует, что конфиденциальные данные могут быть изменены только с помощью контролируемых методов.
| Модификатор | Тот же класс | Дочерний класс | Вне класса |
|---|---|---|---|
public | Да | Да | Да |
protected | Да | Да | Нет |
private | Да | Нет | Нет |
Ключевой момент: Используйте private для внутренних данных, к которым не должно быть прямого доступа, protected для данных, необходимых дочерним классам, и public только для безопасного внешнего доступа.
Задание
ЛегкоДавайте создадим безопасную систему управления сотрудниками, которая демонстрирует, как модификаторы доступа защищают конфиденциальные данные. Вы создадите иерархию классов, где разные уровни информации доступны в зависимости от того, где выполняется код — внутри класса, в дочернем классе или извне.
Вы организуете свой код в трех файлах:
Employee.php— Создайте классEmployee, который управляет данными сотрудников с соответствующими уровнями видимости. Класс должен иметь:publicсвойство$nameдля имени сотрудника (безопасно для всеобщего обозрения)protectedсвойство$employeeIdдля внутреннего идентификатора (необходимо дочерним классам)privateсвойство$salaryдля конфиденциальной информации о зарплате (только этот класс должен иметь к нему прямой доступ)
getSalary(), который возвращает приватную зарплату — это контролируемый способ доступа к защищенным данным. Также добавьте публичный методgetPublicInfo(), который возвращает"[name] works here".Manager.php— Создайте классManager, который расширяетEmployee. Подключите файл Employee. Конструктор должен принимать name, employeeId, salary и название отдела (department). Вызовите родительский конструктор с первыми тремя значениями, затем сохраните отдел в приватном свойстве. Добавьте публичный методgetTeamInfo(), который возвращает"Manager [name] (ID: [employeeId]) leads [department]". Обратите внимание, как дочерний класс может получить доступ к защищенному$employeeId, но ему потребуетсяgetSalary()для доступа к приватной зарплате.main.php— Подключите файл Manager. Вы получите четыре входных значения: имя, ID сотрудника, зарплату (в виде строки, которую вы преобразуете в целое число) и название отдела. Создайте экземплярManagerс этими значениями. Выведите три строки:- Имя менеджера, полученное напрямую (публичное свойство)
- Результат вызова
getTeamInfo() - Результат вызова
getSalary()
Эта задача демонстрирует инкапсуляцию в действии: имя свободно доступно, ID сотрудника передается дочерним классам через защищенную видимость (protected), а зарплата остается заблокированной в родительском классе — доступной только через контролируемый публичный метод.
Шпаргалка
PHP предоставляет три модификатора доступа для управления тем, где можно получить доступ к свойствам и методам:
| Модификатор | Тот же класс | Дочерний класс | Снаружи |
|---|---|---|---|
public | Да | Да | Да |
protected | Да | Да | Нет |
private | Да | Нет | Нет |
Пример:
<?php
class BankAccount {
public $accountHolder; // Доступно отовсюду
protected $accountNumber; // Доступно в этом классе и дочерних классах
private $balance; // Доступно только в этом классе
public function __construct($holder, $number, $balance) {
$this->accountHolder = $holder;
$this->accountNumber = $number;
$this->balance = $balance;
}
public function getBalance() {
return $this->balance;
}
}
$account = new BankAccount("John", "12345", 1000);
echo $account->accountHolder; // Работает - public
echo $account->getBalance(); // Работает - public method
Лучшие практики:
- Используйте
privateдля внутренних данных, к которым не должно быть прямого доступа - Используйте
protectedдля данных, которые необходимы дочерним классам - Используйте
publicтолько для безопасного внешнего доступа
Попробуйте сами
<?php
require_once 'Manager.php';
// Чтение входных данных
$name = trim(fgets(STDIN));
$employeeId = trim(fgets(STDIN));
$salary = intval(trim(fgets(STDIN)));
$department = trim(fgets(STDIN));
// TODO: Создайте экземпляр Manager с входными значениями
// TODO: Выведите имя менеджера (доступ к которому осуществляется напрямую как к публичному свойству)
// TODO: Выведите результат вызова getTeamInfo()
// TODO: Выведите результат вызова getSalary()
?>В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово $thisМетодыСвойстваКонструктор (__construct)Деструктор (__destruct)Итоги — Простой калькулятор4Наследование
Основы наследованияКлючевое слово parent::Переопределение методовКлючевое слово finalАбстрактные классыИтоги — Иерархия сотрудников7Инкапсуляция
Public, Protected, PrivateПодробный разбор модификаторов доступаГеттеры и сеттерыСокрытие данныхConstructor Promotion (8.0)Итоги — Система учета студентов10Продвинутые концепции ООП
Композиция против наследованияВнедрение зависимостейАнонимные классыПеречисления (PHP 8.1)Файберы (PHP 8.1)Глубокое погружение в клонирование объектовГенераторы и итераторы13Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий2Пространства имен и автозагрузка
Введение в пространства именКлючевое слово useСтандарт автозагрузки PSR-4Автозагрузчик ComposerИтоги: структурированный проект5Интерфейсы и контракты
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовИнтерфейс против абстрактного классаType Hinting с интерфейсамиИтоги — Калькулятор фигур8Магические методы
Введение в магические методы__toString и __debugInfo__get, __set, __isset, __unset__call и __callStatic__clone и клонирование объектов__serialize и __unserializeИтоги — Кастомная коллекция11Система типов и обработка ошибок
Объявление типовNullable-типыТипы объединения и пересеченияКлассы исключенийИерархия пользовательских исключенийTry, Catch, FinallyИтоги — Валидатор форм14Проект: Управление библиотекой
Обзор проектаКлассы Book и User3Свойства классов
Свойства экземпляра и статические свойстваКонстанты в классахСтатические методы и свойстваПриватные и защищенные свойстваСвойства Readonly (PHP 8.1)Итоги — Менеджер банковского счета6Полиморфизм
Снова о переопределении методовПолиморфизм через интерфейсыType Hinting и Union TypesПозднее статическое связываниеИтоги — Payment Processor9Трейты
Введение в трейтыИспользование нескольких трейтовРазрешение конфликтов трейтовАбстрактные методы в трейтахТрейты и наследование12Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн Strategy