| |
дних и тех же данных, когда можно хранить
их в программе и сразу же использовать? Это свойство будет инициализироваться
при конструировании объекта класса MysqlTable и обновляться каждый раз при
обращении к методу SetInfo().
То есть наше свойство будет представлять собой аналог "зеркала" записи в
таблице MySQL, по аналогии с "зеркалами" сайтов в Интернете. Класс
MysqlTable должен следить за тем, чтобы оно всегда содержало актуальные
данные — те же самые, что и в реальной таблице.
Но, к сожалению, описанная схема не может быть реализована в PHP напрямую, и
именно по причине обязательного полного копирования переменных. Вот пример,
который породит ошибку:
$t1=new MysqlTable("MyTable");
. . .
function DoIt($t)
{ $t->SetInfo("This is the new info!");
}
. . .
$t=new MysqlTable("MyTableName");
$t->SetInfo("Data");
DoIt($t);
$Inf=$t->GetInfo(); // в $Inf будет строка Data!
Впрочем, в приведенном только что фрагменте это недоразумение можно легко пре-
одолеть, передав функции ссылку на объект:
function DoIt(&$t)
{ $t->SetInfo("This is the new info!");
}
Я намеренно привел здесь пример, когда ограничение на копирование объектов все
же можно обойти относительно безболезненно. Настало время описать неразрешимую
(во всяком случае, похожим методом) задачу. Но прежде обратите внимание, что в
нашем примере объект передается "вглубь" кода (внутрь функции), а не "наружу"
(из
функции). Вот как раз в последнем случае и будет возникать неразрешимая
проблема.
Часть V. Приемы программирования на PHP 480
Но обо всем по порядку. Чтобы чуть сгустить краски и не вдаваться в абстрактные
рассуждения, давайте предположим, что наш класс MysqlTable вообще не допускает
копирования его объектов, а при случайном выполнении такого копирования
работает
совершенно неправильно. Нужно заметить, что это не так уж и далеко от истины,
особенно если мы используем MysqlTable не напрямую, а как базовый для какого-то
другого типа (например, для класса форума).
Мы знаем, что в таком случае объекты этого класса можно передать без побочных
эффектов внутрь функций по ссылке. Сейчас мы остановимся на обратном процессе.
Итак, пусть мы написали более-менее универсальный модуль, в котором есть
единст-
венная интерфейсная функция OpenTable(), создающая новую таблицу в базе дан-
ных и, соответственно, новый объект класса MysqlTable. Специфика этой функции в
том, что в случае, если таблица существует, новый объект не создается, а
возвращает-
ся уже имеющийся. Иными словами, для двух вызовов функции с одинаковыми па-
раметрами должен быть возвращен один и тот же объект, а не две его копии.
Возможно, вы спросите: зачем нам вообще такая функция, когда можно вос-
пользоваться оператором new напрямую? Тогда еще раз перечитайте предпо-
следнюю фразу предыдущего абзаца: "В случае, если таблица уже существует,
новый объект не создается". В то же время оператор new всегда создает но-
вый объект, что нам, конечно, не подходит. Ведь мы договорились никогда не
иметь в программе двух разных объектов, связанных с одной и той же табли-
цей.
Легко сказать — "возвращает уже существующий объект", но несколько сложнее —
реализовать это. Рассмотрим два различных способа, с помощью которых мы можем
достичь цели.
Как следует из законов Мэрфи, "у любой сложной задачи всегда имеется одно
простое, красивое и легкое для понимания… неправильное решение". В нашем
случае это будет возврат из функции объекта класса MysqlTable "обычным"
способом, подразумевающим копирование. Но ведь, по имеющейся между на-
ми договоренности, объекты этого класса нельзя копировать!
Возврат ссылки на объект
Первый прием связан с новой возможностью PHP версии 4 — ссылочными перемен-
ными. Помните, в части III этой книги мы говорили, что функция может возвращать
ссылку на переменную (объект), а не только копию переменной?.. В нашем случае
это
оказывается довольно удобно. Вот как могла бы выглядеть функция OpenTable() и
использование для нее
|
|