Справочник по Ada 2005
7.5 Ограниченные типы
Ограниченный тип — это (вид) тип, для которого не допускается копирование (например, для оператора присваивания). Неограниченный тип — это (вид) тип, для которого копирование разрешено.
Правила допустимости
Если помеченный тип записи содержит какие-либо ограниченные компоненты, то ключевое слово limited должно присутствовать в его определении типа записи record_type_definition. Если ключевое слово limited присутствует в определении derived_type_definition, то его родительский тип и все интерфейсы предков должны быть ограниченными.
В следующих контекстах выражение ограниченного типа не допускается, если это не агрегат, вызов функции или скобочное выражение или квалифицированное выражение, операнд которого разрешен данным правилом:
- выражение инициализации объявления объекта (см. 3.3.1)
- выражение по умолчанию компонента объявления (см. 3.8)
- выражение компонента записи (см. 4.3.1)
- выражение для части предка агрегата расширения (см. 4.3.2)
- выражение позиционного агрегата массива или выражение ассоциации компонента массива (см. 4.3.3)
- квалифицированное выражение инициализированного аллокатора (см. 4.8)
- выражение оператора возврата (см. 6.5)
- выражение по умолчанию или фактический параметр для формального объекта режима in (см. 12.4)
Статическая семантика
Тип является ограниченным, если он один из следующих:
- тип с ключевыми словами limited, synchronized, task или protected в его определении;
- Этот абзац был удалён.
- составной тип с ограниченным компонентом;
- производный тип, родитель которого ограничен и не является интерфейсом.
В противном случае тип является неограниченным.
Для ограниченного типа нет предопределённых операторов равенства.
Требования к реализации
Для агрегата ограниченного типа, используемого для инициализации объекта, как разрешено выше, реализация не должна создавать отдельный анонимный объект для агрегата. Для вызова функции типа с частью типа задачи, защищённого или явно ограниченного типа записи, который используется для инициализации объекта, как разрешено выше, реализация не должна создавать отдельный возвращаемый объект (см. 6.5) для вызова функции. Агрегат или вызов функции должны быть построены непосредственно в новом объекте.
ПРИМЕЧАНИЯ
14 Хотя разрешено записывать инициализации ограниченных объектов, такие инициализации никогда не копируют ограниченный объект. Источник такого оператора присваивания должен быть агрегатом или вызовом функции, и такие агрегаты и вызовы функций должны быть построены непосредственно в целевом объекте.
Абзацы с 10 по 15 были удалены.
15 Как показано в 7.3.1, неопознанный ограниченный тип может стать неограниченным при определенных условиях.
Примеры
Пример пакета с ограниченным типом:
package IO_Package is
type File_Name is limited private;
type File_Name is limited private;
procedure Open (F : in out File_Name);
procedure Close(F : in out File_Name);
procedure Read (F : in File_Name; Item : out Integer);
procedure Write(F : in File_Name; Item : in Integer);
private
type File_Name is
limited record
Internal_Name : Integer := 0;
end record;
end IO_Package;
procedure Close(F : in out File_Name);
procedure Read (F : in File_Name; Item : out Integer);
procedure Write(F : in File_Name; Item : in Integer);
private
type File_Name is
limited record
Internal_Name : Integer := 0;
end record;
end IO_Package;
package body IO_Package is
Limit : constant := 200;
type File_Descriptor is record ... end record;
Directory : array (1 .. Limit) of File_Descriptor;
...
procedure Open (F : in out File_Name) is ... end;
procedure Close(F : in out File_Name) is ... end;
procedure Read (F : in File_Name; Item : out Integer) is ... end;
procedure Write(F : in File_Name; Item : in Integer) is ... end;
begin
...
end IO_Package;
Limit : constant := 200;
type File_Descriptor is record ... end record;
Directory : array (1 .. Limit) of File_Descriptor;
...
procedure Open (F : in out File_Name) is ... end;
procedure Close(F : in out File_Name) is ... end;
procedure Read (F : in File_Name; Item : out Integer) is ... end;
procedure Write(F : in File_Name; Item : in Integer) is ... end;
begin
...
end IO_Package;
ПРИМЕЧАНИЯ
16 Примечания к примеру: В приведённом примере внешняя подпрограмма, использующая IO_Package, может получить имя файла, вызвав Open, и в дальнейшем использовать его в вызовах Read и Write. Таким образом, вне пакета имя файла, полученное из Open, действует как своего рода пароль; его внутренние свойства (например, содержащая числовое значение) неизвестны, и над именем файла нельзя выполнять другие операции (например, сложение или сравнение внутренних имён). Важно, что клиенты пакета не могут создавать копии объектов типа File_Name.
Этот пример характерен для любого случая, когда требуется полный контроль над операциями типа. Такие пакеты служат двойной цели. Они препятствуют пользователю использовать внутреннюю структуру типа. Они также реализуют понятие инкапсулированного типа данных, где единственными операциями над типом являются те, что указаны в спецификации пакета.
Тот факт, что полный вид File_Name явно объявлен limited, означает, что передача параметров всегда будет по ссылке, а результаты функций всегда будут построены непосредственно в целевом объекте (см. 6.2 и 6.5).