В чем разница между public, private и protected в PHP?
Основное различие между модификаторами доступа
Модификаторы доступа public, private и protected определяют, откуда можно обращаться к свойствам и методам класса. Это основа инкапсуляции — одного из ключевых принципов ООП.
1. Public — доступен отовсюду
Свойства и методы с модификатором public доступны из любого места: внутри класса, из дочерних классов и из внешнего кода (глобальной области видимости).
<?php
class Animal {
public $name = 'Unknown';
public function makeSound() {
return 'Some sound';
}
}
$dog = new Animal();
echo $dog->name; // 'Unknown' — работает
echo $dog->makeSound(); // 'Some sound' — работает
?>
2. Private — доступен только внутри класса-родителя
Свойства и методы с модификатором private видны только в том классе, где они объявлены. Даже дочерние классы не имеют к ним доступа. Это самый строгий уровень инкапсуляции.
<?php
class BankAccount {
private $balance = 1000;
public function getBalance() {
return $this->balance; // Внутри класса — работает
}
}
class SavingsAccount extends BankAccount {
public function showBalance() {
return $this->balance; // Ошибка! Private недоступен
}
}
$account = new BankAccount();
echo $account->balance; // Ошибка! Private недоступен извне
echo $account->getBalance(); // 1000 — через публичный метод
?>
3. Protected — доступен внутри класса и в дочерних классах
Модификатор protected — золотая середина. Он скрывает данные от внешнего кода, но разрешает доступ из родительского класса и всех его наследников.
<?php
class Vehicle {
protected $vin = 'VIN123';
public function getVin() {
return $this->vin;
}
}
class Car extends Vehicle {
public function showVin() {
return $this->vin; // Работает! Protected доступен в наследнике
}
}
$myCar = new Car();
echo $myCar->vin; // Ошибка! Извне — нет
echo $myCar->getVin(); // 'VIN123' — через публичный метод родителя
echo $myCar->showVin(); // 'VIN123' — через публичный метод наследника
?>
Когда что использовать?
- Public — для интерфейса класса: методов, которые должны быть доступны всем (например,
getUser(),save()). Свойства лучше делать private/protected. - Private — для внутренних деталей реализации, которые не должны меняться в наследниках (например, пароль, внутренние счётчики).
- Protected — когда нужно, чтобы наследники могли переопределить или использовать базовую логику (например, шаблонный метод).
Практический пример
<?php
class User {
private $passwordHash; // Только внутри класса
protected $role; // Доступно наследникам
public $username; // Доступно всем
public function __construct($username, $password) {
$this->username = $username;
$this->passwordHash = password_hash($password, PASSWORD_DEFAULT);
}
private function checkPassword($password) {
return password_verify($password, $this->passwordHash);
}
public function login($password) {
return $this->checkPassword($password); // Вызов private-метода
}
}
class Admin extends User {
public function getRole() {
return $this->role; // Работает, так как protected
// return $this->passwordHash; // Ошибка! Private
}
}
?>
Запомните правило: public — для всех, protected — для семьи (класс + наследники), private — только для себя. Используйте самый строгий модификатор, который возможен в конкретной ситуации. Это сделает ваш код более надёжным и понятным.
<<Дополнение: Практические советы по выбору модификатора
Первый ответ отлично объясняет теорию. Я добавлю несколько практических правил, которые помогут новичкам не ошибаться:
- Все свойства класса делайте private по умолчанию. Открывайте доступ только через публичные методы (геттеры/сеттеры). Это защитит данные от некорректного изменения.
- Protected используйте только когда уверены, что дочерние классы должны переопределять поведение. Например, если у вас есть базовый класс
PaymentGatewayи наследникиPaypalGateway,StripeGateway— методы с основной логикой можно сделать protected. - Избегайте public-свойств. Даже если свойство кажется безобидным (например,
$name), лучше сделать его private и добавить геттер. В будущем вы сможете добавить валидацию без изменения внешнего кода.
<?php
// Плохо
class User {
public $email; // Можно изменить на что угодно
}
// Хорошо
class User {
private $email;
public function setEmail($email) {
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
$this->email = $email;
} else {
throw new InvalidArgumentException('Некорректный email');
}
}
public function getEmail() {
return $this->email;
}
}
?>
Помните: инкапсуляция — это не просто синтаксис, а инструмент для создания надёжного кода. Чем строже контроль доступа, тем меньше шансов случайно «сломать» логику класса извне.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги