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