Первый прием связан с новой возможностью PHP версии 4— ссылочными переменными. Помните, в части III этой книги мы говорили, что функция может возвращать ссылку на переменную (объект), а не только копию переменной?.. В нашем случае это оказывается довольно удобно. Вот как могла бы выглядеть функция OpenTable() и использование для нее ссылок (листинг 31.4):
Листинг 31.4. Использование ссылок
// Массив всех уже открытых таблиц. Ключи — имена таблиц, значения —
// соответствующие объекты.
$Tables=array();
. . .
// Функция OpenTable() возвращает ссылку на объект, соответствующий
// таблице MySQL с заданным именем. Копии объектов не создаются.
function &OpenTable($name,$Fields="")
{ global $Tables;
if(!Isset($Tables[$name]))
$Tables[$name]=new MysqlTable($name,$Fields);
return $Tables[$name];
}
. . .
// Вот так мы должны использовать эту функцию.
$Tbl1=&OpenTable("MyTable"); // создает новый объект
$Tbl2=&OpenTable("OtherTable"); // создает объект
$TblEqualsTo1=&OpenTable("MyTable"); // возвращает имеющийся объект!
// Теперь $Tbl1 и $TblEqualsTo1 ссылаются на один и тот же объект.
// То есть изменение $Tbl1 тут же отразится на $TblEqualsTo1,
// и наоборот.
Опытный программист сразу же заметит в подходе предыдущего примера два значительных недостатка. Оба они связаны с несовершенством механизма управления ссылками в PHP.
r Если пропустить перед вызовом функции оператор & (взятие ссылки), то функция вернет не ссылку на объект, а копию этого объекта. При этом программа не выдаст никакого предупреждения и, скорее всего, будет даже работать верно — до тех пор, пока для копии объекта не будет вызван метод, ради которого мы и хотели избежать копирования. Вообразите себе муки программиста, отлаживающего такую программу, которая отказалась правильно работать по этой причине — ведь & может быть пропущен очень далеко от того места, где возникла ошибка!
r У неопытного программиста, использующего ваш класс, может возникнуть искушение скопировать $Tbl1 в новую переменную "обычным"
образом — при помощи оператора =. Или же он может по ошибке пропустить &, когда объявляет функцию со ссылочным параметром.
Мы видим, что два указанных недостатка приводят к тому, что программу становится очень трудно отлаживать. А такие программы, как показал многолетний опыт программирования, не только никуда не годятся — они приносят разработчику лишь огорчения, сокращая его век.
Есть ли альтернатива ссылкам? Оказывается, есть. Правда, она сопряжена с большими сложностями при разработке классов, но зато полностью лишена недостатков, описанных выше. Это — фактическое отделение набора методов, отвечающих за взаимодействие с объектом класса (то есть интерфейса класса) от его реализации.