Раздел 11.1 - Описание настраиваемых модулей

Часто бывает удобно сначала создать более обобщенную версию подпрограммы или пакета, а затем используя ее, - более специфические подпрограммы или пакеты. Такая возможность в языке Ada называется настраиваемыми модулями; это то же самое, что и темплейты в C++. Настраиваемый модуль чем-то похож на директивы препроцессора "#define" в C, хотя выполняемая языком проверка типов внутри настраиваемого модуля делает его гораздо более безопасным.

Вероятно, проще понять это на примере. Для начала, напишем процедуру, которая меняет местами два значеня типа Integer:

  -- Это описание (спецификация):
  procedure Swap(Left, Right : in out Integer);

  -- ..а это тело: 
  procedure Swap(Left, Right : in out Integer) is
    Temporary : Integer;
  begin
    Temporary := Left;
    Left := Right;
    Right := Temporary;
  end Swap;

Процедура Swap хороша, но слишком ограничена. Мы не можем использовать Swap для того, чтобы менять местами величины типа Float, Unbounded_String или какие-либо другие. Более обобщенная версия подпрограммы Swap, причем такая, чтобы было возможно заменить тип Integer настраиваемым типом - это как раз то, что нам необходимо. Настраиваемая версия Swap будет выглядеть следующим образом:

  -- Это описание (спецификация):
  generic
    type Element_Type is private;
  procedure Generic_Swap(Left, Right : in out Element_Type);

  -- .. а это тело:
  procedure Generic_Swap(Left, Right : in out Element_Type) is
    Temporary : Element_Type;
  begin
    Temporary := Left;
    Left := Right;
    Right := Temporary;
  end Generic_Swap;

В общем случае, для того, чтобы создать настраиваемую версию подпрограммы (или пакета), необходимо написать подпрограмму с использованием нескольких настраиваемых типов. Затем, перед подпрограммой или пакетом написать ключевое слово ``generic'' и список того, что необходимо сделать настраиваемым. Этот список называют формальными параметрами настройки; он похож на список параметров в описании процедуры. Cмысл фразы ``is private'' будет пояснен ниже.

Для использования настраиваемой подпрограммы (или пакета) необходимо создать реальную подпрограмму (или пакет) из настраиваемой. Этот процесс называется конкретизацией, а результат называется конкретизированным модулем или экземпляром модуля. Это, конечно, слишком громкие термины для такой простой концепции. Например, вот каким образом можно создать три экземпляра процедуры Swap из настраиваемой процедуры:

  procedure Swap is new Generic_Swap(Integer);
  procedure Swap is new Generic_Swap(Float);
  procedure Swap is new Generic_Swap(Unbounded_String);

Заметим, что при конкретизации настраиваемого модуля парамеры ему нужно передавать точно так же, как и при обыкновенном вызове подпрограммы.

После этого можно вызывать процедуру Swap, которая принимает в качестве параметров переменные типа Integer, Float и Unbounded_String. Таким образом, если и A и B являются переменными типа Integer, Swap(A,B) поменяет их местами. Точно также, как и для любой из подпрограмм, имеющих одинаковые имена, Ada во время компиляции определит какую из них вызывать, в зависимости от типов аргументов.

Ниже приведена простая тестовая программа для процедуры Generic_Swap:

with Generic_Swap;

procedure Tswap is
 procedure Swap is new Generic_Swap(Integer);
 A, B : Integer;
begin
 A := 5;
 B := 7;
 Swap(A, B);
 -- Теперь A=7, а B=5.
 
end Tswap;

Для простоты мы показали конкретизацию процедуры Swap внутри процедуры Tswap, хотя в реальных программах почти все группируется в пакет, и тогда конкретизации будут находиться внутри его тела.


К этому разделу упражнение отсутствует.

Вы можете перейти к следующему разделу.


Вы можете также:

PREVIOUS Вернуться к предыдущему разделу

OUTLINE  Вернуться к содержанию Урока 11

David A. Wheeler (dwheeler@ida.org)

Перевод: Юрий Королев   Общая редакция перевода: Г.Ю. Сисюк

Исходная копия этого документа находится по адресу "http://www.adahome.com/Tutorials/Lovelace/s11s1.htm".

Исходная копия перевода размещена на сайте http://www.ada-ru.org