Настраиваемые подпрограммы
Рассмотрим простой пример описания настраиваемой подпрограммы.
Однажды скомпилированная, она в последствии может быть помещена в инструкцию спецификатора совместности контекста with
в других программных модулях.
Напомним также, что настраиваемый модуль нельзя указывать в инструкции спецификатора использования контекста use.
Спецификация модуля настраиваемой подпрограммы содержит ключевое слово generic, после которого следует список формальных параметров настройки и далее - спецификация процедуры:
generic
type Element is private; -- Element - это параметр настраиваемой -- подпрограммы procedure Exchange(A, B : in out Element); |
Тело настраиваемой процедуры описывает реализацию алгоритма работы процедуры и представляется как отдельно компилируемый модуль. Примечательно, что оно идентично не настраиваемой версии.
procedure Exchange(A, B : in out Element) is
Temp : Element; begin T := Temp; T := B; B := Temp; end Exchange; |
Код, показанный выше, является простым шаблоном для процедуры, которая может быть реально создана.
Следует обратить внимание на то, что этот код не может быть непосредственно вызван.
Это подобно описанию типа, поскольку не производится никакого распределения пространства памяти или генерации машинного кода.
Для создания реальной процедуры, то есть, экземпляра процедуры которую можно вызвать, необходимо выполнить конкретизацию настраиваемой процедуры:
procedure Swap is new Exchange(Integer); |
Следует заметить, что в показанном выше примере конкретизация настраиваемой процедуры осуществлена с использованием простого позиционного сопоставления формального и фактического параметров настройки. В дополнение к позиционному сопоставлению, Ада позволяет использовать именное сопоставление формальных и фактических параметров настройки (при большом количестве параметров настройки, именное сопоставление улучшает читабельность). Показанную выше конкретизацию настраиваемой процедуры можно осуществить с помощью использования именного сопоставления следующим образом:
procedure Swap is new Exchange(Element => Integer); |
Здесь, Integer является фактическим параметром настройки, а Element - формальным параметром настройки.
Процедура Swap может быть вызвана (и она будет вести себя) как будто она была описана следующим образом:
procedure Swap (A, B : in out Integer) is Temp : Integer; begin . . . end Swap; |
procedure Swap is new Exchange(Character); procedure Swap is new Exchange(Element => Account); -- ассоциация по имени |
Компилятор будет определять к какой конкретно процедуре производится вызов используя информацию о типе параметра.