Сеттеры (setters) служат для изменения внутреннего состояния объекта. Как и геттеры, они именуются особым образом. К сеттерам обычно добавляется префикс set, если этот сеттер что-то устанавливает и add — если добавляет.
<?php
$point1 = new Point(10, 11);
$point2 = new Point(-3, 3);
$segment = new Segment($point1, $point2);
$segment->getStartPoint(); // (10, 11)
$segment->setStartPoint(new Point(3, 8)); // Допустимо, потому что new Point(3, 8) — выражение
$segment->getStartPoint(); // (3, 8)
На практике изменения объектов происходят почти всегда с помощью сеттеров, и крайне редко — через изменение свойства напрямую. Причём объекты (впрочем, как и любая абстракция) иногда хранят внутри себя свойства, которые нельзя изменять снаружи (например, соединение с базой данных), и для них не делают сеттеров.
Вообще говоря, с сеттерами связано много головной боли. Несмотря на сокрытие данных, встроенное в объекты, можно легко создать ситуацию, в которой из одного объекта извлекается другой объект и меняется. Естественно, исходный объект об этих изменениях ничего не знает. Проблема обостряется тогда, когда один объект используется по всему приложению. В такой ситуации он ведёт себя как глобальная переменная (в худшем её проявлении). Изменения, сделанные в одном месте, коснутся всего.
Например, ранее мы создали класс для работы с рациональными числами. Если бы методы add()
и sub()
изменяли объект, на котором вызываются, то получить неверные расчёты стало бы крайне просто. Достаточно использовать одно рациональное число в нескольких местах, и любое его изменение повлияет на всех, кто использует это число. Абсолютно такая же ситуация и с графическими примитивами на плоскости.
<?php
$point1 = new Point(10, 11);
$point2 = new Point(-3, 3);
$segment1 = new Segment($point1, $point2);
$segment2 = new Segment($point2, $point1);
// Функция moveUp перемещает весь отрезок на три значения вверх.
// Она не возвращает новый отрезок, а изменяет сам объект.
$segment1->moveUp(3);
print_r($segment1); // => [(10, 14), (-3, 6)]
Если внутри moveUp()
происходит изменение точек (вместо создания новых), то такое изменение повлияет и на segment2
, хотя мы и не собирались его перемещать.
<?php
// Такое поведение неожиданно
// Сегмент изменился, хотя напрямую его никто не менял
print_r($segment2); // => [(-3, 6), (10, 14)]
Существует ли способ сделать всё красиво? Нет, фундаментальная проблема "изменяемое состояние" может быть убрана только отказом от изменения и созданием нового на основе старого. Последний приём подходит не всегда, но мы уже использовали его на практике, например, в рациональных числах.
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.