Отправляет email-рассылки с помощью сервиса Sendsay

PHP 5 для начинающих

  Все выпуски  

Основное отличие объектной модели PHP 5


Вниманию читателей!

Отдельные выпуски рассылки в той или иной мере взаимосвязаны. С предыдущими выпусками Вы можете ознакомиться:

  1. в архиве рассылки (оригиналы выпусков);
  2. на сайте рассылки (исправленные и дополненные версии).

# # #

Вы также можете подписаться на рассылку "PHP 5: Новые возможности".

PHP 5 для начинающих

В предлагаемом материале подробно описано, в чем заключается основное ограничение объектной модели PHP 4, а также каким образом удалось его преодолеть в PHP 5.

Как уже говорилось, основным недостатком объектной модели в PHP 3 и 4 было то, что объекты передавались по значению, а не по ссылке.

[Подсказка]Подсказка

Вспомнить, что такое передача данных по значению и по ссылке поможет секция "Передача аргументов" в статье "Функции", опубликованной ранее в рамках рассылки "PHP 5 для начинающих".

По умолчанию PHP передает данные в функцию по значению (Пример 4.1, «Передача данных по значению»), что вполне оправдано, так как позволяет защитить передаваемые данные от случайного изменения внутри функции. Передача данных по ссылке, если это по каким-то причинам все же необходимо, требует от программиста явного указания (использования символа &).

Пример 4.1. Передача данных по значению

<?php

function foo($bar) 1
{
    $bar = 'WOW!'; 2
}

$bar = 'Oops!'; 3
foo($bar); 4
print $bar; 5

?>
            
3

Создается переменная $bar и ей присваивается значение Oops!.

[Замечание]Замечание

Переменная $bar создается в глобальном контексте. Это значит, что она просуществует с момента создания до окончания работы программы; кроме того, эта переменная, несмотря на совпадение имен, не идентична переменной $bar, существующей в локальном контексте функции foo().

4 1

Вызывается функция foo(), ей передается значение глобальной переменной $bar.

Функция foo() принимает переданное ей значение и присваивает его локальной переменной $bar.

[Подсказка]Подсказка

Еще говорят, что в функцию передается копия переменной $bar.

[Замечание]Замечание

Аргумент $bar функции foo() имеет смысл только в локальном контексте этой функции. Вне его (в глобальном контексте) эта переменная просто не существует. Из этого следует, что она создается при вызове функции и уничтожается по завершению ее работы; кроме того, она, несмотря на совпадение имен, не идентична переменной $bar, объявленной в глобальном контексте.

2

Локальной переменной $bar присваивается значение WOW!.

[Замечание]Замечание

Поскольку локальная переменная $bar не идентична одноименной глобальной переменной, то изменение значения локальной переменной никак не скажется на значении глобальной переменной.

5

Выводится значение глобальной переменной $bar.

Oops! 1
1

Как видим, значение переменной $bar осталось неизменным.


Такой же механизм передачи - как для обычных данных - используется по умолчанию в PHP 4 и по отношению к объектам (Пример 4.2, «Передача объектов в PHP). Но при ближайшем рассмотрении оказывается, что объекты, в отличие от обычных (скалярных) данных, требуют передачи как раз по ссылке, а не по значению (именно так ведут себя по умолчанию объекты в других объектно-ориентированных языках программирования).

Пример 4.2. Передача объектов в PHP 4

<?php

function nurse($baby) 1
{
    $baby->isHungry = false; 2
}

$john = new stdClass; 3
$john->isHungry = true; 4
nurse($john); 5
var_dump($john->isHungry); 6

?>
            
3

Создадим новый объект Джон ($john) класса stdClass (это встроенный класс, который не содержит ни одного свойства и ни одного метода; своего рода аналог пустого массива).

4

Добавим объекту Джон новое свойство - признак голода ($isHungry) и установим его в истинное (true) состояние (понятно ведь, что наш новорожденный зверски голоден).

5

Ну, а раз голоден, то надо его покормить.

1

Функция кормление() (nurse()) принимает в качестве аргумента объект ребенок ($baby) - копию переданного ей из глобального контекста объекта (вспомним, что по умолчанию работает механизм передачи данных по значению).

2

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

6

Проверим, сыт ли новорожденный.

bool(true) 1
1

Не правда ли, странно? Джон по-прежнему голоден, несмотря на только что проведенное кормление.


На самом деле, ничего странного в полученном результате нет. Достаточно вспомнить, что в функцию nurse() был передан не сам объект $john, а его копия. Таким образом, на время кормления у Джона появился некий двойник, который сразу же после кормления канул обратно в небытие вместе с предназначавшимся для Джона молоком. Понятно, что это явно не то, что можно было бы ожидать в данной ситуации.

Конечно, только что рассмотренное поведение («Передача объектов по значению») свойственно объектной модели лишь по умолчанию. Передача объектов по ссылке все же возможна, если задать ее явным образом (при помощи символа &).

Пример 4.3. Передача объекта по ссылке

<?php

function nurse(&$baby) 1
{
    $baby->isHungry = false;
}

$john = new stdClass;
$john->isHungry = true;
nurse($john); 2
var_dump($john->isHungry);

?>
            
2 1

В функцию передается не копия объекта Джон, а ссылка на этот объект. Таким образом, кормиться будет уже не его двойник, а сам Джон.

bool(false) 1
1

Мы все же не позволили Джону умереть голодной смертью.


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

Энди Гутманс (Andy Gutmans) предложил заменить сами объекты указателями (handles) на них [4]. Это решение и было воплощено в PHP 5.

Пример 4.4. Представление объектов в PHP 5

print new stdClass;
Object id #1 1
1

Указатели представляют собой порядковые номера (идентификаторы) объектов в глобальной таблице.


Тем самым удается обеспечить такое же поведение объектов, как и при передаче по ссылке (Пример 4.5, «Передача объектов в PHP).

[Замечание]Замечание

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

Пример 4.5. Передача объектов в PHP 5

<?php

function nurse($baby) 1
{
    $baby->isHungry = false;
}

$john = new StdClass;
$john->isHungry = true;
nurse($john); 2
var_dump($john->isHungry);

?>
            
2 1

Объект передается в вызываемую функцию по ссылке без явного указания сделать это при помощи символа & (по умолчанию).

bool(false) 1
1

Значение инспектируемого свойства объекта вполне соответствует ожидаемому.


Снятие основного ограничения объектной модели открыло возможности для ее дальнейшего развития. Скрипты стали выполняться быстрее и требовать меньше памяти, так как передавать одно целое число легче, чем копировать большие объемы данных. Программирорвание стало более интуитивным и простым. [4]

  1. Каковы негативные последствия основного ограничения объектной модели в PHP 4? Выберите правильные ответы.

  2. Почему Джон остался голоден (Пример 4.2, «Передача объектов в PHP)? Выберите верный ответ.

    1. Функцию следовало назвать babysitter().

    2. Не было указано количество молока.

    3. То был не Джон.

    4. Молоко оказалось прокисшим.

  3. Определите, под какой версией PHP, четвертой или пятой, исполнялся следующий скрипт.

    [Подсказка]Подсказка

    При приравнивании объектов действуют механизмы, аналогичные тем, которые используются для передачи объектов в функцию.

    <?php
    
    $obj1 = new stdClass;
    $obj1->x = 1;
    
    $obj2 = $obj1;
    $obj2->x = 2;
    
    echo $obj1->x, $obj2->x;
    
    ?>
                    
    22

«Ответы и решения к Глава 4, Основное отличие объектной модели PHP 5»

[Подсказка]Подсказка

Если в процессе выполнения контрольных заданий возникли проблемы, которые трудно решить самостоятельно, Вы всегда можете обратиться за помощью на этот форум.

Created with DocBook


В избранное