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