Ада-95. Компилятор GNAT

       

Расширение существующего пакета


Рассмотрим случай когда возникает необходимость расширения пакета который уже содержит некоторое множество описаний.

Например, в пакете Stacks может понадобиться дополнительный сервис просмотра Peek.

Если в текущий момент времени пакет Stacks используется многими модулями, то такая модификация, путем добавления нового сервиса, потребует значительных затрат на перекомпиляцию всех зависимых модулей, причем, включая и те модули которые не будут использовать новый сервис.

Следовательно, для логического расширения уже существующего пакета предпочтительнее использовать дочерний пакет который будет существовать абсолютно отдельно. Например:

package Stacks is

type Stack is private; procedure Push(Onto : in out Stack; Item : Integer); procedure Pop(From : in out Stack; Item : out Integer); function Full(Item : Stack) return Boolean; function Empty(Item : Stack) return Boolean;

private

-- скрытая реализация стека ... -- точка A

end Stacks;

package Stacks.More_Stuff is

function Peek(Item : Stack) return Integer;

end Stacks.More_Stuff;



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

Следовательно, дочерний пакет видит всю приватную часть спецификации родительского пакета.

В показанном выше примере, пакет Stacks.More_Stuff является дочерним пакетом для пакета Stacks.

Значит, дочерний пакет Stacks.More_Stuff "видит" все описания пакета Stacks, вплоть до точки A.

Необходимо заметить, что для сохранения приватности описаний родительского пакета, Ада не позволяет включать в спецификацию дочернего пакета приватную часть спецификации родительского пакета.

Примечание:

Согласно правил именования файлов, принятым в системе компилятора GNAT, спецификация и тело пакета Stacks должны быть помещены в файлы:

stacks.ads и stacks.adb

соответственно, а спецификация и тело дочернего пакета Stacks.More_Stuff

- в файлы:

stacks-more_stuff.ads и stacks-more_stuff.adb




Клиенту, которому необходимо использовать функцию Peek, просто необходимо включить дочерний пакет в инструкцию спецификатора совместности контекста with:

with Stacks.More_Stuff;

procedure Demo is

X : Stacks.Stack;

begin

Stacks.Push(X, 5); if Stacks.More_Stuff.Peek = 5 then

. . .

end Demo;

Следует заметить, что включение дочернего пакета в инструкцию спецификатора совместности контекста with автоматически подразумевает включение в инструкцию with

всех пакетов-родителей.

Однако, инструкция спецификатора использования контекста use

таким образом не работает.

То есть, область видимости может быть получена пакетом только в базисе пакета.

with Stacks.More_Stuff; use Stacks; use More_Stuff;

procedure Demo is

X : Stack;

begin

Push(X, 5); if Peek(x) = 5 then

. . .

end Demo;

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

При этом, однако, сами подпрограммы не могут иметь дочерние модули.


Содержание раздела