В предлагаемом материале подробно описано, в чем заключается основное ограничение объектной модели PHP 4, а также каким образом удалось его преодолеть в PHP 5.
Как уже говорилось, основным недостатком объектной модели в PHP
3 и 4 было то, что объекты передавались по значению, а не по ссылке.
Подсказка
Вспомнить, что такое передача данных по значению и по ссылке поможет секция "Передача аргументов" в статье "Функции", опубликованной ранее в рамках рассылки "PHP 5 для начинающих".
Передача данных по значению.
По умолчанию PHP передает данные в функцию по значению (Пример 4.1, «Передача данных по значению»), что вполне оправдано, так как позволяет защитить передаваемые данные от случайного изменения внутри функции. Передача данных по ссылке, если это по каким-то причинам все же необходимо, требует от программиста явного указания (использования символа &).
Создается переменная $bar и ей присваивается значение Oops!.
Замечание
Переменная $bar создается в глобальном контексте. Это значит, что она просуществует с момента создания до окончания работы программы; кроме того, эта переменная, несмотря на совпадение имен, не идентична переменной $bar, существующей в локальном контексте функции
foo().
Вызывается функция foo(), ей передается значение глобальной
переменной $bar.
Функция foo() принимает переданное ей значение и присваивает его локальной переменной $bar.
Подсказка
Еще говорят, что в функцию передается копия переменной $bar.
Замечание
Аргумент $bar функции foo() имеет смысл только в локальном контексте этой функции. Вне его (в глобальном контексте) эта переменная просто не существует. Из этого следует, что она создается при вызове функции и уничтожается по завершению ее работы; кроме того, она, несмотря на совпадение имен, не идентична переменной $bar, объявленной в глобальном контексте.
Локальной переменной $bar присваивается значение WOW!.
Замечание
Поскольку локальная переменная $bar не идентична одноименной глобальной переменной, то изменение значения локальной переменной никак не скажется на значении глобальной переменной.
Выводится
значение глобальной переменной $bar.
Oops!
Как
видим, значение переменной $bar осталось неизменным.
Передача объектов по значению
Такой же механизм передачи - как для обычных данных - используется по умолчанию в PHP 4 и по отношению к объектам (Пример 4.2, «Передача объектов в PHP 4»). Но при ближайшем рассмотрении оказывается, что объекты, в отличие от обычных (скалярных) данных, требуют передачи как раз по ссылке, а не по значению (именно так ведут себя по умолчанию объекты в других объектно-ориентированных языках программирования).
Пример 4.2. Передача объектов в PHP 4
<?php
function nurse($baby)
{
$baby->isHungry = false;
}
$john = new stdClass;
$john->isHungry = true;
nurse($john);
var_dump($john->isHungry);
?>
Создадим новый объект Джон ($john) класса stdClass (это встроенный класс, который не содержит ни одного свойства и ни одного метода; своего рода
аналог пустого массива).
Добавим объекту Джон новое свойство - признак голода ($isHungry) и установим его в истинное (true) состояние (понятно ведь, что наш новорожденный зверски голоден).
Ну, а раз голоден, то надо его покормить.
Функция кормление() (nurse())
принимает в качестве аргумента объект ребенок ($baby) - копию переданного ей из глобального контекста объекта (вспомним, что по умолчанию работает механизм передачи данных по значению).
Простоты
ради опустим сам процесс кормления и только сбросим признак голода, присвоив ему значение false.
Проверим, сыт ли новорожденный.
bool(true)
Не правда ли, странно? Джон по-прежнему голоден, несмотря на только что проведенное кормление.
На самом деле, ничего
странного в полученном результате нет. Достаточно вспомнить, что в функцию nurse() был передан не сам объект $john, а его копия. Таким образом, на время кормления у Джона появился некий двойник, который сразу же после кормления канул обратно в небытие вместе с предназначавшимся для Джона молоком. Понятно, что это явно не то, что можно было бы ожидать в данной ситуации.
Передача объектов по ссылке
Конечно, только что рассмотренное поведение («Передача объектов по значению») свойственно объектной модели лишь по умолчанию. Передача объектов по ссылке все же возможна, если задать ее явным образом (при помощи символа &).
Пример 4.3. Передача объекта по ссылке
<?php
function nurse(&$baby)
{
$baby->isHungry = false;
}
$john = new stdClass;
$john->isHungry = true;
nurse($john);
var_dump($john->isHungry);
?>
В функцию передается не копия объекта Джон, а ссылка
на этот объект. Таким образом, кормиться будет уже не его двойник, а сам Джон.
bool(false)
Мы все же не позволили Джону умереть голодной смертью.
К сожалению, такое решение не является полноценным, так как оно не устраняет причину проблемы - неправильный способ передачи данных. И как результат - невозможность реализовать полноценную объектную модель.
Указатели на объект
ЭндиГутманс (AndyGutmans) предложил заменить сами объекты указателями (handles) на них [4].
Это решение и было воплощено в PHP 5.
Пример 4.4. Представление объектов в PHP 5
print new stdClass;
Object id #1
Указатели представляют собой порядковые номера (идентификаторы) объектов в глобальной таблице.
Существуют все же некоторые технические различия в реализации ссылок и указателей, но на поведении объектов это не
сказывается. Поэтому в дальнейшем будем считать, что объекты передаются по ссылке.
Пример 4.5. Передача объектов в PHP 5
<?php
function nurse($baby)
{
$baby->isHungry = false;
}
$john = new StdClass;
$john->isHungry = true;
nurse($john);
var_dump($john->isHungry);
?>
Объект передается в вызываемую функцию по ссылке без явного указания сделать это при помощи символа
& (по умолчанию).
bool(false)
Значение
инспектируемого свойства объекта вполне соответствует ожидаемому.
Снятие основного ограничения объектной модели открыло возможности для ее дальнейшего развития. Скрипты стали выполняться быстрее и требовать меньше памяти, так как передавать одно целое число легче, чем копировать большие объемы данных. Программирорвание стало более интуитивным и простым. [4]
Контрольные вопросы и задания
Каковы негативные последствия основного ограничения объектной модели в PHP 4? Выберите правильные ответы.
Замедление работы скриптов.
Препятствия на пути дальнейшего развития объектной модели.
Запрет
на использование в коммерческих проектах.
Запутанное кодирование.
Неправильное поведение объектов.
Отсутствие поддержки кириллицы.
Невозможность одновременного использования с объектами ассоциативных массивов.
Если в процессе выполнения контрольных заданий возникли проблемы, которые трудно решить самостоятельно, Вы всегда можете обратиться за помощью на этот форум.