Расширение существующего пакета
Расширение существующего пакета
Рассмотрим случай когда возникает необходимость расширения пакета который уже содержит некоторое множество описаний.Например, в пакете 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; |
Необходимо также заметить, что подпрограммы (процедуры и функции) могут быть дочерними модулями пакета (правила их использования достаточно очевидны).При этом, однако, сами подпрограммы не могут иметь дочерние модули.