ученикам: ушел в отпуск до 15-го июня. в отпуске буду по возможности отвечать на вопросы, но могу пропадать

Работа с геттерами и сеттерами

Давайте рассмотрим следующий класс:

<?php class User { public $name; public $age; // Метод для изменения возраста юзера: public function setAge($age) { // Проверим возраст на корректность: if ($this->isAgeCorrect($age)) { $this->age = $age; } } // Метод для проверки возраста: private function isAgeCorrect($age) { return $age >= 18 and $age <= 60; } } ?>

Как вы видите, у нас есть публичные свойства $name и $age, публичный метод setAge для изменения возраста и приватный метод проверки возраста isAgeCorrect.

Очевидно, что предполагается, что возраст всегда будет меняться через метод setAge, так как в нем выполняется проверка возраста на корректность.

Однако, ничего не мешает сделать так:

<?php $user = new User; // Вместо вызова setAge установим некорректный возраст напрямую: $user->age = 100500; // и у нас получится! ?>

Упс... Получается, что мы надеемся, что везде и всегда возраст будет меняться через setAge, но случайно другой программист или мы сами можем напрямую обратиться к свойству и записать в него все, что угодно.

Это ошибкоопасное место и с этим нужно что-то сделать.

Для решения проблемы можно объявить возраст приватным:

<?php class User { public $name; private $age; //!! объявим возраст приватным // Метод для изменения возраста юзера: public function setAge($age) { // Проверим возраст на корректность: if ($this->isAgeCorrect($age)) { $this->age = $age; } } // Метод для проверки возраста: private function isAgeCorrect($age) { return $age >= 18 and $age <= 60; } } ?>

Теперь установить возраст напрямую (корректный или нет - не важно) не получится:

<?php $user = new User; // Теперь установить возраст напрямую не получится: $user->age = 100500; // увидим ошибку PHP! ?>

Отлично, мы получили то, что хотели. Но теперь есть другая проблема: мы не можем прочитать возраст снаружи, так как он приватный:

<?php $user = new User; // Правильным образом установим возраст: $user->setAge(50); //!! Попытка прочитать новый возраст приведет к ошибке PHP: echo $user->age; // а нам бы этого не хотелось... ?>

Для решения проблемы сделаем еще один метод getAge, с помощью которого мы будем прочитывать значения свойства $age:

<?php class User { public $name; private $age; // объявим возраст приватным //!! Метод для чтения возраста юзера: public function getAge() { return $this->age; } // Метод для изменения возраста юзера: public function setAge($age) { // Проверим возраст на корректность: if ($this->isAgeCorrect($age)) { $this->age = $age; } } // Метод для проверки возраста: private function isAgeCorrect($age) { return $age >= 18 and $age <= 60; } } ?>

Теперь мы свободно можем и менять, и получать возраст:

<?php $user = new User; // Установим возраст: $user->setAge(50); //!! Прочитаем новый возраст: echo $user->getAge(); // выведет 50 ?>

Еще раз: почему мы не пишем и не читаем из свойства напрямую - потому-что нам при записи в свойства нужна какая-то проверка, поэтому мы и городим весь этот огород.

Такой подход, который мы сейчас сделали, - стандартный. В терминах этого подхода метод getAge называется геттером (англ getter), а метод setAge - сеттером (англ setter).

Этот подход удобно использовать тогда, когда нам нужна какая-то проверка в сеттере.

Очень часто бывает так, что даже если нам не нужны никакие проверки - все равно свойство объявляется приватным, а для доступа к нему используются геттеры и сеттеры.

Почему? Потому что, возможно, нам захочется добавить проверку в дальнейшем и, если все изменения свойства в коде делаются через сеттер, нам не придется вносить правки в код снаружи класса - мы просто внесем одну правку в сам сеттер.

Сделайте класс Employee, в котором будут следующие private свойства: name (имя), age (возраст) и salary (зарплата).

Сделайте геттеры и сеттеры для всех свойств класса Employee.

Дополните класс Employee приватным методом isAgeCorrect, который будет проверять возраст на корректность (от 1 до 100 лет). Этот метод должен использоваться в сеттере setAge перед установкой нового возраста (если возраст не корректный - он не должен меняться).

Пусть зарплата наших работников хранится в долларах. Сделайте так, чтобы геттер getSalary добавлял в конец числа с зарплатой значок доллара. Говоря другими словами в свойстве salary зарплата будет хранится просто числом, но геттер будет возвращать ее с долларом на конце.