Основы объектно-ориентированного программирования
Шрифт:
Если бы r было пустой ссылкой, то такой же в результате присваивания стала бы и ссылка в поле loved_one объекта O1.
Рис. 8.13. После присваивания ссылки
Сравнение ссылок
Наряду с присваиванием возникает необходимость и в тесте - проверить, присоединены ли две ссылки к одному и тому же объекту. Для этого есть оператор эквивалентности =.
Если x и y– сущности ссылочного типа, то выражение:
истинно тогда и только тогда, когда обе ссылки пусты или присоединены к одному и тому же объекту. Противоположный оператор "не эквивалентно" записывается как /=.
Выражение:
истинно в ситуации, представленной на рис.8.13 и ложно для ситуации рис.8.12 .
Заметьте, в операциях эквивалентности сравниваются ссылки, а не объекты, к которым они присоединены. Так что если две ссылки присоединены к разным объектам, результатом операции эквивалентности будет false, даже если объекты имеют все поля с одинаковыми значениями. Операции, сравнивающие объекты, а не ссылки, будут введены позднее.
Значение void
Получить пустую ссылку достаточно просто - при инициализации по умолчанию все ссылки пусты. Однако удобно иметь специальное имя для ссылки, доступной в любом контексте и имеющей значение void . Предопределенный компонент
играет эту роль.
Обычно компонент Void используется в тестах, проверяющих пустоту ссылок:
и для того, чтобы присвоить некоторой ссылке это значение:
В результате последнего присваивания происходит отсоединение ссылки от объекта, и она становится пустой. Эта ситуация показана на следующем рисунке:
Рис. 8.14. Отсоединение ссылки от объекта
| Присваивание Void ссылке не оказывает никакого влияния на объект, ранее присоединенный к ссылке, - разрывается только связь между ссылкой и объектом. Было бы некорректно рассматривать эту операцию как освобождение памяти, так как другие ссылки могут продолжать быть связанными с объектом (на рисунке x может быть отсоединено от объекта O1, но другие ссылки могут быть еще присоединены к нему). Об управлении памятью смотри следующую лекцию. |
Клонирование и сравнение объектов
Ссылочное присваивание приводит к тому, что две или несколько ссылок присоединяются к одному объекту. Иногда необходима другая форма присваивания, в результате которой мы хотим получить не копию ссылки, а копию объекта. Эта цель достигается при вызове функции клонирования clone.
Если y присоединено к объекту OY, выражение
означает создание нового объекта OX , такого, что он имеет те же поля, что и OY, и все соответствующие поля имеют идентичные значения. Если y равно void, то значение clone (y) также void.
Скопировать присоединенный к y объект и связать копию со ссылкой x позволяет присваивание:
Вот иллюстрация этого механизма:
Рис. 8.15. Клонирование объекта
Наряду со сравнением ссылок необходим механизм, позволяющий сравнивать объекты. Этой цели служит функция equal . Вызов:
возвращает значение true, если и только если x и y оба имеют значение void или присоединены к двум объектам с идентичными полями. После выполнения присваивания с клонированием [1], состояние, непосредственно следующее за присваиванием, удовлетворяет equal (x, y).
| Возможно, вы удивляетесь, почему у функции clone есть аргумент, а у функции equal– их два. Для ОО-стиля характерен квалифицируемый вызов в форме: y.twin и x.is_equal (y). Ответ появится в разделе обсуждения, но это будет еще не скоро, так что попытайтесь догадаться сами. |
Копирование объектов
Функция clone создает новую копию существующего объекта. Иногда целевой объект уже существует, и все, что необходимо, это скопировать значения полей. Процедура copy выполняет эту работу. Она вызывается обычным образом:
Сущности x и y должны быть одного и того же типа; эффект от выполнения - копирование полей объекта, присоединенного к y, в соответствующие поля объекта, присоединенного к x.
Как и во всех вызовах компонента, вызов copy требует, чтобы целевой объект x был не пуст. Дополнительно требуется, чтобы и y был не пуст. Эта неспособность иметь дело с пустыми ссылками отличает copy от clone.
| Требование не пустоты y настолько важно, что должен существовать способ для его формального выражения. Фактически речь идет о более общей проблеме: как программа может задать предусловия на аргументы, передаваемые клиентом при ее вызове. Такие предусловия, являясь частным случаем общего понятия "утверждение" в деталях будут обсуждаться в последующих лекциях. Аналогично, нам хотелось бы уметь выражать в виде постусловия семантическое свойство, отмеченное выше, - результат выполнения clone удовлетворяет equal. |