Простой интерфейс
Первую версию интерфейса пакета, задающего стек, можно выразить следующим образом. Заметим, что ключевое слово package (пакет) вводит интерфейс; тело, появляющееся позднее, вводится сочетанием package body (тело пакета).
package REAL_STACKS is type STACK_CONTENTS is array (POSITIVE range <>) of FLOAT; type STACK (capacity: POSITIVE) is record implementation: STACK_CONTENTS (1..capacity); count: NATURAL := 0; end record; procedure put (x: in FLOAT; s: in out STACK); procedure remove (s: in out STACK); function item (s: STACK) return FLOAT; function empty (s: STACK) return BOOLEAN; Overflow, Underflow: EXCEPTION; end REAL_STACKS;Этот интерфейс перечисляет экспортированные элементы: тип STACK - для объявления стеков, вспомогательный тип STACK_CONTENTS, используемый типом STACK, четыре открытые подпрограммы (процедуры и функции) и два исключения. Клиентские пакеты будут опираться только на интерфейс (предполагается, что создающие их программисты имеют представление о семантике, связанной с программами).
Этот пример наводит на несколько общих замечаний:
- Удивительно видеть все детали представления стека в объявлениях типов STACK и STACK_CONTENTS, появившихся в том, что должно быть чистым интерфейсом. Кратко рассмотрим причину этой проблемы и способ ее устранения.
- В отличие от класса, пакет не определяет тип. Тип STACK следует определить отдельно. Одним из следствий этого отделения для программиста, создающего пакет вокруг реализации абстрактного типа данных, является необходимость изобретения двух различных имен - одно для пакета, другое - для типа. Другое следствие состоит в том, что подпрограммы имеют еще один аргумент по сравнению со своими ОО-аналогами: здесь все они имеют первым аргументом стек s, в то время как для класса он задается неявно (см. предыдущие лекции).
- Объявление может определять не только тип сущности, но и ее исходное значение. Здесь объявление count в типе STACK предписывает исходное значение 0. Оно устраняет необходимость явной операции инициализации, задаваемой процедурой создания (конструктором) класса.
Однако этот способ не работает, если требуется более сложная инициализация. - Для понимания объявления типа следует привести некоторые детали языка Ada: POSITIVE и NATURAL обозначают подтипы INTEGER, включающие, соответственно, положительные и неотрицательные целые, спецификация типа вида array (TYPE range <>), где <> известно как Box-символ, описывает шаблон для типов массивов. Для получения действительного типа из такого шаблона нужно выбрать конечный отрезок TYPE. Здесь это делается при определении типа STACK, использующем интервал [1..capacity] типа POSITIVE. STACK является примером параметризованного типа. Любое объявление сущности типа STACK должно задавать фактическое значение емкости стека capacity, как в: s: STACK (1000)
- В языке Ada каждый аргумент подпрограммы характеризуется статусом in, out или in out, определяющим права подпрограммы на использование фактических аргументов (только для чтения, только для записи, для обновления). В отсутствии явного ключевого слова состояние по умолчанию - in.
- Наконец, интерфейс определяет два имени исключений Overflow и Underflow. Исключение - это ситуация, когда из-за ошибок прерывается нормальный порядок вычислений. Интерфейс пакета должен перечислить любые исключения, которые могут возбуждаться в процессе работы подпрограмм пакета и передаваться для обработки клиентам. Подробно механизм исключений языка Ada описывается ниже.