Spec-Zone.ru › Ada 2012
Справочник по Ada 2012

3.9.4 Типы интерфейсов

Тип интерфейса — это абстрактный помеченный тип, предоставляющий ограниченную форму множественного наследования. Помеченный тип, тип задачи или защищённый тип могут иметь один или несколько типов интерфейсов в качестве предков.

Синтаксис

определение_типа_интерфейса ::=
[limited | task | protected | synchronized] interface [and список_интерфейсов]
список_интерфейсов ::= тип_интерфейсаметка_подтипа {and тип_интерфейсаметка_подтипа}

Статическая семантика

Тип интерфейса (также называемый интерфейсом) — это специфический абстрактный помеченный тип, определённый с помощью определения_типа_интерфейса.
Интерфейс со служебными словами limited, task, protected или synchronized в его определении называется соответственно ограниченным интерфейсом, интерфейсом задачи, интерфейсом защищённого типа или синхронизированным интерфейсом. Кроме того, все интерфейсы задач и защищённых типов являются синхронизированными интерфейсами, а все синхронизированные интерфейсы являются ограниченными интерфейсами.
Тип задачи или защищённый тип, производные от интерфейса, являются помеченными типами. Такие помеченные типы называются синхронизированными помеченными типами, так же как и синхронизированные интерфейсы и частные расширения, в объявлении которых встречается служебное слово synchronized.
Интерфейс задачи является абстрактным типом задачи. Интерфейс защищённого типа является абстрактным защищённым типом.
Тип интерфейса не имеет компонентов.
Тип_интерфейсаметка_подтипа в списке_интерфейсов называет родительский подтип; его тип является родительским типом. Тип интерфейса наследует определяемые пользователем примитивные подпрограммы от каждого родительского типа так же, как производный тип наследует определяемые пользователем примитивные подпрограммы от своих родительских типов (см. 3.4).

Правила легальности

Все определяемые пользователем примитивные подпрограммы типа интерфейса должны быть абстрактными подпрограммами или нулевыми процедурами.
Тип подтипа, указанного в списке_интерфейсов, должен быть типом интерфейса.
Тип, производный от неограниченного интерфейса, должен быть неограниченным.
Интерфейс, производный от интерфейса задачи, должен включать служебное слово task в своём определении; любой другой тип, производный от интерфейса задачи, должен быть частным расширением или типом задачи, объявленным в объявлении задачи (см. 9.1).
Интерфейс, производный от интерфейса защищённого типа, должен включать служебное слово protected в своём определении; любой другой тип, производный от интерфейса защищённого типа, должен быть частным расширением или типом защищённого типа, объявленным в объявлении защищённого типа (см. 9.4).
Интерфейс, производный от синхронизированного интерфейса, должен включать одно из служебных слов task, protected или synchronized в своём определении; любой другой тип, производный от синхронизированного интерфейса, должен быть частным расширением, типом задачи, объявленным в объявлении задачи, или типом защищённого типа, объявленным в объявлении защищённого типа.
Ни один тип не может быть получен из интерфейса задачи и интерфейса защищённого типа одновременно.
В дополнение к местам, где обычно применяются правила легальности (см. 12.3), эти правила применяются также в частной части экземпляра обобщённого блока.

Динамическая семантика

Выполнение определения_типа_интерфейса создаёт тип интерфейса и его первый подтип.
ПРИМЕЧАНИЯ
85 Неограниченные типы интерфейсов имеют предопределённые неабстрактные операторы равенства. Эти операторы могут быть переопределены с помощью определяемых пользователем абстрактных операторов равенства. Такие операторы потребуют явного переопределения для любого неабстрактного потомка интерфейса.

Примеры

Пример ограниченного интерфейса и синхронизированного интерфейса, расширяющего его:
type Queue is limited interface;
procedure Append(Q : in out Queue; Person : in Person_Name) is abstract;
procedure Remove_First(Q : in out Queue;
Person : out Person_Name) is abstract;
function Cur_Count(Q : in Queue) return Natural is abstract;
function Max_Count(Q : in Queue) return Natural is abstract;
-- См. 3.10.1 для Person_Name.
Queue_Error : exception;
-- Append вызывает Queue_Error, если Cur_Count(Q) = Max_Count(Q)
-- Remove_First вызывает Queue_Error, если Cur_Count(Q) = 0
type Synchronized_Queue is synchronized interface and Queue; -- см. 9.11
procedure Append_Wait(Q : in out Synchronized_Queue;
Person : in Person_Name) is abstract;
procedure Remove_First_Wait(Q : in out Synchronized_Queue;
Person : out Person_Name) is abstract;
...
procedure Transfer(From : in out Queue'Class;
To : in out Queue'Class;
Number : in Natural := 1) is
Person : Person_Name;
begin
for I in 1..Number loop
Remove_First(From, Person);
Append(To, Person);
end loop;
end Transfer;
Это определяет интерфейс очереди Queue для очереди людей. (Аналогичный дизайн можно создать для определения любого типа очереди, просто заменив Person_Name соответствующим типом.) Интерфейс Queue имеет четыре операции диспетчеризации: Append, Remove_First, Cur_Count и Max_Count. Также показан текст тела оператора Transfer для всего класса. Каждое неабстрактное расширение Queue должно предоставить реализации по крайней мере своих четырёх операций диспетчеризации, так как они абстрактные. Любой объект типа, производного от Queue, может быть передан в Transfer в качестве операнда From или To. Два операнда не должны быть одного и того же типа в любом данном вызове.
Интерфейс Synchronized_Queue наследует четыре операции диспетчеризации от Queue и добавляет две дополнительные операции диспетчеризации, которые ожидают, если необходимо, вместо того, чтобы генерировать исключение Queue_Error. Этот синхронизированный интерфейс может быть реализован только типом задачи или защищённого типа, и таким образом гарантирует безопасный одновременный доступ.
Пример использования интерфейса:
type Fast_Food_Queue is new Queue with record ...;
procedure Append(Q : in out Fast_Food_Queue; Person : in Person_Name);
procedure Remove_First(Q : in out Fast_Food_Queue; Person : out Person_Name);
function Cur_Count(Q : in Fast_Food_Queue) return Natural;
function Max_Count(Q : in Fast_Food_Queue) return Natural;
...
Cashier, Counter : Fast_Food_Queue;
...
-- Добавить George (см. 3.10.1) в очередь кассира:
Append (Cashier, George);
-- После оплаты, переместить George в очередь очереди сэндвичей:
Transfer (Cashier, Counter);
...
Интерфейс, такой как Queue, может быть непосредственно использован в качестве родителя нового типа (как показано здесь), или может быть использован в качестве предка, когда тип является производным. В любом случае, примитивные операции интерфейса наследуются. Для Queue, реализация четырёх унаследованных процедур должна быть предоставлена. Внутри вызова Transfer, вызовы будут передаваться в реализации Append и Remove_First для типа Fast_Food_Queue.
Пример интерфейса задачи:
type Serial_Device is task interface; -- см. 9.1
procedure Read (Dev : in Serial_Device; C : out Character) is abstract;
procedure Write(Dev : in Serial_Device; C : in Character) is abstract;
Интерфейс Serial_Device имеет две операции диспетчеризации, которые должны быть реализованы с помощью записей задач (см. 9.1).


Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API