Как происходит отслеживание свободного экстента? |
Переменные, присваивание и ссылки
9.5. Ссылочное присваивание
Значения, которыми мы манипулируем, — в частности, поля объектов, соответствующие атрибутам их классов, — могут быть базисными значениями, такими как целые и булевские, а могут быть и ссылками. До сих пор мы применяли присваивание к базисным значениям, но нам понадобится и присваивание ссылок. Это необходимо, например, при построении связанных структур данных, таких как список остановок метро, где каждая остановка содержит ссылку на связанную с ней станцию и на следующую остановку на линии.
Построение остановок метро
Реализация класса STOP требует такого ссылочного присваивания. Интерфейс класса включает спецификации следующих компонентов:
set_station (ms: STATION) — Связать эту остановку с ms require station_exists: ms /= Void ensure station_set: station = ms link (s: STOP) — Сделать s следующей остановкой на линии ensure next_set: right = s
Реализация требует установки значений для атрибутов класса station и right, для чего необходимо присваивание. Приведем текст метода (не ограничиваясь интерфейсом):
set_station (ms: STATION) — Связать эту остановку с ms require station_exists: ms /= Void do station:=ms ensure _set: station = ms end link (s: STOP) — Сделать s следующей остановкой на линии. do right := s ensure next_set: right = s end
Ссылочное присваивание присоединяет ссылку к новому объекту. Предыдущее значение ссылки могло быть void (объект отсутствует) или присоединено к другому объекту (могло быть даже присоединено к тому же самому объекту, и тогда присваивание ничего бы не меняло). Для иллюстрации этих возможностей рассмотрим переменные s1 и s2 типа STOP и два оператора создания:
create s1.set_station (Station_Balard) create s2.set_station (Station_Issy)
Оба оператора используют процедуру создания set_station. Это необходимо, поскольку мы уже переписали класс STOP следующим образом:
class STOP create set_station feature station: STATION right: STOP set_station (s: STATION) ... Как выше ... link (s: STOP) ... Как выше ... invariant station_exists: station /= Void end
Операторы создают два объекта:
Благодаря процедуре создания set_station ссылки на станцию присоединяются к двум предопределенным объектам типа STATION. Ссылки right остаются void, так все ссылки изначально устанавливаются в void, а set_station ничего не делает с right.
Построение линии метро
Для соединения двух остановок можно использовать оператор:
s1.link(s2)
Он обновляет right-ссылку первого объекта:
Результат является следствием ссылочного присваивания в процедуре link:
link (s: STOP) — Сделать s следующей остановкой на линии. do right:=s ensure right_set: right = s end
Это пример ссылочного присваивания, присоединяющего ссылку. Здесь ссылка (поле right объекта STOP слева) была до присваивания равна void; мы присвоили ей непустую ссылку s2, в результате right была присоединена ко второму STOP-объекту. Ссылочное присваивание можно использовать для отсоединения от объекта, делая ссылку пустой — void. Для примера добавим в класс STOP следующую процедуру:
make_last — Сделать эту остановку последней на линии. do right := Void ensure no_right: right = Void end
Здесь используется значение Void, всегда обозначающее пустую ссылку. Следующие три вызова дают один и тот же эффект в предположении, что v имеет значение void:
s1.make_last s1.link (Void) s1.link (v)
Чтобы еще немного поиграть со ссылками, рассмотрим предыдущий пример, но уже с тремя остановками:
create s1.set_station (Station_Balard) create s2.set_station (Station_Issy) create s3.set_station (Station_Montrouge) s1.link( s2) s2.link( s3) s3.make_last
Результатом является дополнение предыдущего рисунка, показывающее мини-линию метро:
9.6. Программирование со ссылками
Ссылка идентифицирует объект. Их использование дает ряд преимуществ: моделирование отношения "Знаю о", поддержка связанных структур. Но у ссылок есть и обратная, темная сторона: динамические псевдонимы заставляют быть крайне внимательными при работе со ссылками.
Ссылки как инструмент моделирования
Один объект может включать ссылку на другой объект, представляя концепцию "знаю о" (об этом объекте). Эту концепцию можно сравнить с концепцией "содержит" (другой объект). Разницу демонстрирует пример с двумя интерпретациями глагола "имеет".
Ключевая разница в разделении: два автомобиля могут иметь одну и ту же марку, но ни один уважающий себя автомобиль не будет разделять мотор с другим автомобилем. Создавая ОО-программную модель, в первом случае используем ссылку на объект, во втором — подобъект.
Развернутые типы помогают моделировать подобъекты. Такая гибкость моделирования крайне важна при построении модели сложной системы.