Menu
Coddy logo textTech

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

Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy. Урок 39 из 91.

Теперь, когда вы понимаете три модификатора доступа, давайте рассмотрим, как они ведут себя в сценариях наследования. Главное, что нужно понять: члены с модификатором protected становятся доступными дочерним классам, а члены с модификатором private остаются скрытыми даже от дочерних классов.

<?php
class Vehicle {
    public $brand;
    protected $engineType;
    private $serialNumber;
    
    public function __construct($brand, $engine, $serial) {
        $this->brand = $brand;
        $this->engineType = $engine;
        $this->serialNumber = $serial;
    }
    
    private function getSerial() {
        return $this->serialNumber;
    }
    
    protected function getEngineInfo() {
        return $this->engineType;
    }
}

class Car extends Vehicle {
    public function getDetails() {
        return $this->brand . " - " . $this->getEngineInfo();
        // $this->serialNumber вызовет ошибку - private!
        // $this->getSerial() также не сработает - private method!
    }
}

$car = new Car("Toyota", "V6", "ABC123");
echo $car->getDetails();

Вывод:

Toyota - V6

Класс Car может получить доступ к $brand (public) и вызвать getEngineInfo() (protected), но не имеет доступа к $serialNumber или getSerial(), поскольку они private для Vehicle. Это различие позволяет делиться некоторыми внутренними деталями с дочерними классами, сохраняя другие полностью скрытыми.

Ключевой момент: Используй protected, когда дочерним классам нужен доступ к внутренним данным или методам, и private, когда даже дочерние классы не должны обращаться к определённым деталям реализации.

challenge icon

Задание

Легко

Давайте создадим систему управления устройствами, которая демонстрирует, как модификаторы доступа ведут себя при наследовании. Вы создадите базовый класс Device со свойствами разных уровней видимости, а затем расширите его с помощью класса Smartphone, показывающего, к каким членам дочерние классы могут и не могут получать доступ.

Вы организуете код в трёх файлах:

  • Device.php: создайте класс Device, представляющий электронные устройства с разными уровнями конфиденциальности данных. Добавьте:
    • свойство public $brand для названия производителя;
    • свойство protected $modelNumber для внутренней идентификации;
    • свойство private $manufacturingCode для данных, предназначенных только для фабрики.
    Конструктор должен принимать все три значения. Добавьте метод private getManufacturingCode(), который возвращает manufacturing code. Добавьте метод public getModelInfo(), который возвращает "Model: [modelNumber]". Наконец, добавьте метод public getFullCode(), который возвращает "[brand]-[manufacturingCode]". Это демонстрирует, как сам класс может получать доступ к собственным private-членам.
  • Smartphone.php: создайте класс Smartphone, который расширяет Device. Подключите файл Device. Конструктор должен принимать brand, modelNumber, manufacturingCode и название operating системы. Вызовите конструктор parent с первыми тремя значениями, затем сохраните OS в private свойстве. Добавьте public метод getDeviceDetails(), который возвращает "[brand] [modelNumber] running [os]". Обратите внимание: вы можете напрямую обращаться к public $brand и protected $modelNumber, но не можете напрямую обращаться к private $manufacturingCode: вместо этого нужно использовать inherited public метод getFullCode().
  • main.php: подключите файл Smartphone. Вы получите четыре inputs: brand, modelNumber, manufacturingCode и operating систему. Создайте instance Smartphone с этими значениями. Print три строки:
    • результат вызова getDeviceDetails();
    • результат вызова inherited метода getModelInfo();
    • результат вызова inherited метода getFullCode().

Эта задача подчёркивает ключевое различие: ваш класс Smartphone может свободно использовать protected $modelNumber, inherited от Device, но private $manufacturingCode и getManufacturingCode() остаются полностью скрытыми: доступ к ним возможен только через public interface, который Device решит предоставить.

Попробуйте сами

<?php
require_once 'Smartphone.php';

// Читать входные данные
$brand = trim(fgets(STDIN));
$modelNumber = trim(fgets(STDIN));
$manufacturingCode = trim(fgets(STDIN));
$os = trim(fgets(STDIN));

// TODO: Создайте экземпляр Smartphone с входными значениями

// TODO: Выведите результат getDeviceDetails()

// TODO: Выведите результат унаследованного метода getModelInfo()

// TODO: Выведите результат унаследованного метода getFullCode()
?>
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор PHP