Чтобы помочь Вам разобраться в том, как эти, столь различные механизмы, "уживаются" друг с другом, мы создали пример пакета в котором они используются вместе. Сейчас Вам не обязательно понимать все мелкие нюансы этого примера, хотя у для этого у Вас уже вполне достаточно информации. При первом прочтении сосредоточтесь, чтобы увидеть картину в целом.
Разработанный нами пример - это настраиваемый пакет для создания стека, очень похожий на пример, который мы видели в разделе о настраиваемых модулях. Впрочем, теперь мы сможем использовать ссылочные типы для реализации неограниченного стека, и снять все ограничения на его размер. Поскольку мы хотим разрешить пользователям выполнять присваивание стеков, то будем использовать "Ada.Finalization", а сам тип Stack реализуем как потомок от типа Controlled, чтобы можно было управлять операциями финализации и присваивания (тип Controlled мы обсуждали в последнем разделе Урока 7).
Как и раньше, у нас будут операции помещения и извлечения из стека. Давайте еще добавим операцию "Empty" для очистки содержимого стека и булевскую функцию "Is_Empty", возвращающую True, если в стеке нет данных. Кроме того, добавим еще операцию "=", возвращающую True если два стека равны (два стека равны в том случае, если они имеют одинаковую длину и содержат одинаковые данные, размещенные в одинаковом порядке).
Рекомендуем Вам, при создании повторно используемых типов, добавлять еще и операцию "перемены мест" (swap) [Wheeler 1992]; заметим, что операция swap может быть реализована очень эффективно с использованием ссылочных типов. Наличие операции "Length" позволяет определить количество элементов в стеке. Кроме того, обратите внимание на новый тип - "Natural". Это предопределенный подтип типа Integer, начинающийся с нуля. Поскольку стек не может содержать отрицательное количество элементов, то логичнее было бы, чтобы функция Length возвращала величину типа Natural, а не Integer.
При реализации неограниченных типов необходимо всегда переопределять стандартные процедуры Adjust и Finalize. Если Вы этого не сделали, то, вероятнее всего, здесь что-то не так. Если бы мы не переопределили Adjust, присваивание привело бы к тому, что два "разных" стека ссылались бы на один и тот же элемент. В результате, если за этим последует финализация, то она затронет оба стека, а это не должно происходить. Если бы мы не переопределили операцию Finalize, то не выполнялось бы необходимое освобождение памяти для элементов.
Теперь, учитывая все выше сказанное, приведем спецификацию пакета Generic_Stack:
Обратите внимание на ловкий трюк, который мы провернули: в пакете даже нет полного описания элемента! Поскольку элемент никуда не передается и никем не возвращается, то описание его типа можно оставить неполным, а завершить в теле настраиваемого пакета.
Так как пакет является настраиваемым, при использовании его необходимо конкретизировать каким-то типом. Для примера, конкретизируем его так, чтобы можно было помещать в стек величины типа Integer:
И наконец, напишем короткую тестовую программу, демонстрирующую использование нашего настраиваемого стека:
В теле настраиваемого пакета содержатся операции, определенные в его спецификации и использующие ссылочные типы, о чем мы уже упоминали. Теперь можете спокойно переходить к изучению тела пакета Generic_Stack сопоставлять его со спецификацией, с примером конкретизации (создающим стек элементов типа Integer), другим примером конкретизации (создающим стек стеков элементов типа Integer), короткой демонстрационной программой и более длинной программой в которой стеки встречаются на каждом шагу.
Могут ли пользователи пакета Generic_Stack, описанного выше, использовать тип Stack_Node_Access и манипулировать внутренней структурой стека?
Перейти к предыдущему разделу | Перейти к следующему разделу | Вернуться к содержанию Урока 12 |
---|
David A. Wheeler (dwheeler@ida.org)
Исходная копия этого документа находится по адресу
"http://www.adahome.com/Tutorials/Lovelace/s12sf.htm".
Исходная копия перевода размещена на сайте http://www.ada-ru.org
Перевод: Юрий Королев
Общая редакция перевода: Г.Ю. Сисюк