Сокрытие информации
Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy. Урок 41 из 91.
Сокрытие информации — это принцип, лежащий в основе инкапсуляции: идея о том, что class должен предоставлять только необходимое и скрывать детали своей внутренней реализации. Хотя модификаторы доступа и геттеры/сеттеры являются инструментами, сокрытие информации — это философия проектирования, которая определяет, как их использовать.
Цель состоит в том, чтобы создать чёткую границу между тем, что делает класс (его public-интерфейсом), и тем, как он это делает (его internal-реализацией). Такое разделение означает, что вы можете изменить внутреннее устройство, не затрагивая код, который использует класс:
<?php
class Temperature {
private float $celsius;
public function setCelsius(float $value): void {
$this->celsius = $value;
}
public function getCelsius(): float {
return $this->celsius;
}
public function getFahrenheit(): float {
return ($this->celsius * 9/5) + 32;
}
}
$temp = new Temperature();
$temp->setCelsius(25);
echo $temp->getCelsius() . "C = " . $temp->getFahrenheit() . "F";
Output:
25C = 77Fclass хранит температуру internally в градусах Цельсия, но пользователям не нужно это знать. Позже можно изменить internal хранилище на Fahrenheit или Kelvin, и пока public методы продолжают работать таким же образом, внешний код не перестанет работать.
Ключевой момент: Сокрытие информации защищает ваш код от изменений. Скрывайте детали реализации, открывайте только стабильные интерфейсы — и ваши классы станет проще поддерживать и изменять со временем.
Задание
ЛегкоДавайте создадим конвертер валют, демонстрирующий информационное сокрытие в действии. Вы создадите class, который хранит деньги internally в одной валюте, но может seamlessly конвертировать их в несколько валют и обратно, при этом внешний код никогда не узнает, как именно хранятся данные.
Вы организуете свой код в двух файлах:
Money.php: CreateMoneyclass, который internally хранит все суммы в cents (как integer), чтобы избежать проблем с точностью чисел с плавающей точкой. Эта деталь реализации должна быть полностью скрыта от пользователейclass.classдолжен предоставлять:- private property для хранения суммы в cents
setDollars(float $amount): принимает сумму в dollars и сохраняет её internally как centsgetDollars(): возвращает сумму в dollars (float, 2 десятичных знака)setEuros(float $amount): принимает euros и конвертирует их в cents по курсу: 1 EUR = 1.10 USDgetEuros(): возвращает сумму, конвертированную в euros (float, 2 десятичных знака)getInternalValue(): возвращает raw значение в cents (integer) для debugging
main.php: Подключите файл Money. Вы получите два inputs: сумму в dollars и сумму в euros. Создайте экземплярMoney. Сначала установите сумму в dollars (конвертированную в float) и выведите три строки: значение в dollars, equivalent в euros и internal значение в cents. Затем установите сумму в euros (конвертированную в float) и снова выведите те же три значения.
Преимущество этого дизайна заключается в том, что внешний код работает со знакомыми значениями в dollars и euros, совершенно не зная, что всё internally хранится в cents. Позже вы могли бы изменить internal хранение, используя другую базовую валюту или другую стратегию точности, и при условии, что public методы продолжат работать корректно, внешний код не пришлось бы изменять.
Форматируйте все значения в dollars и euros ровно с 2 десятичными знаками. Каждое значение должно выводиться в отдельной строке, что в общей сложности даёт шесть строк Output.
Попробуйте сами
<?php
require_once 'Money.php';
// Чтение входных данных
$dollarAmount = floatval(trim(fgets(STDIN)));
$euroAmount = floatval(trim(fgets(STDIN)));
// TODO: Создать экземпляр Money
// TODO: Установить сумму в долларах и вывести:
// - Значение в долларах (2 знака после запятой)
// - Эквивалент в евро (2 знака после запятой)
// - Внутреннее значение в центах (целое число)
// TODO: Установить сумму в евро и вывести:
// - Значение в долларах (2 знака после запятой)
// - Эквивалент в евро (2 знака после запятой)
// - Внутреннее значение в центах (целое число)
?>В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово $thisМетодыСвойстваКонструктор (__construct)Деструктор (__destruct)Повторение — простой калькулятор4Наследование
Основы наследованияКлючевое слово parent::Переопределение методовКлючевое слово finalАбстрактные классыПовторение — иерархия сотрудников7Инкапсуляция
Public, Protected, PrivateМодификаторы доступа подробноГеттеры и сеттерыСокрытие информацииПродвижение конструктора (8.0)Повторение — система учёта студентов2Пространства имён и автозагрузка
Введение в пространства имёнКлючевое слово useСтандарт автозагрузки PSR-4Автозагрузчик ComposerПовторение — структурированный проект5Интерфейсы и контракты
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовИнтерфейс и абстрактный классАннотация типов с интерфейсамиПовторение — калькулятор фигур8Магические методы
Введение в магические методы__toString и __debugInfo__get, __set, __isset, __unset__call и __callStatic__clone и клонирование объектов__serialize и __unserializeПовторение — пользовательская коллекция3Свойства классов
Свойства экземпляра и статические свойстваКонстанты в классахСтатические методы и свойстваПриватные и защищённые свойстваСвойства только для чтения (PHP 8.1)Повторение — менеджер банковского счёта6Полиморфизм
Повторение переопределения методовПолиморфизм через интерфейсыАннотации типов и объединённые типыПозднее статическое связываниеПовторение — обработчик платежей9Трейты
Введение в трейтыИспользование нескольких трейтовРазрешение конфликтов трейтовАбстрактные методы в трейтахТрейты и наследование12Паттерны проектирования, часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн StrategyПотренируйтесь самостоятельно: Онлайн-компилятор PHP