Мы привыкли к тому, что данные в PHP всегда передаются по значению. Так происходит и при присваивании, и при передаче данных в функции.
<?php
$a = 5;
$b = $a;
$a = 4;
print_r($b); // => 5
Это правило применимо ко всем данным без исключения. Если мы хотим сделать передачу по ссылке, то нужно использовать &
.
<?php
$a = 5;
// Теперь $a и $b ссылаются на одни и те же данные
$b = &$a;
$a = 4;
print_r($b); // => 4
Но объекты ведут себя подобно передаче по ссылке даже без &
.
По этой причине многие считают, что передача объектов всегда происходит по ссылке. Это не верно. Тот механизм, который используется для передачи объектов, внешне ведёт себя точно так же, как и передача по ссылке, но это другой механизм.
<?php
$p1 = new Point();
$p1->x = 3;
$p1->y = 5;
// p1 и p2 содержат указатель на один и тот же объект
$p2 = $p1;
$p2->x = 100;
print_r($p1->x); // => 100
Когда создается объект, в переменную записывается не он сам, а указатель (pointer) на него. Указатель можно воспринимать как идентификатор (номер) объекта, находящегося где-то в памяти. Когда мы присваиваем переменной объект $p2 = $p1
, то происходит копирование этого идентификатора, но сам он не меняется. Другими словами, идентификатор всегда указывает на тот же самый объект. Поэтому создается впечатление, что объекты передаются по ссылке как при присваивании, так и при передаче объектов в функции.
<?php
function setX(Point $point, int $x)
{
// point указывает на переданный объект, это не копия
// изменение меняет сам объект
$point->x = $x;
}
$point = new Point();
$point->x = 3;
$point->y = 4;
setX($point, 8);
print_r($point->x); // => 8
По этой причине работа с объектами резко отличается от того, что мы изучали раньше. Например, функции, меняющие объекты, редко что-то возвращают наружу. И эти же функции, почти никогда не бывают чистыми, ведь, меняя объекты, они влияют на внешнее окружение. Популярные языки программирования строят работу с объектами на основе императивной парадигмы, что в общем случае не обязательно. С другой стороны, есть ряд задач, в которых удобнее работать с объектами в декларативном стиле, например, при обработке коллекций. Чуть позже мы познакомимся с этим подходом.
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.