Справочник по Ada 95
3.10.1 Неполные объявления типов
Нет особых ограничений на тип, указанный в типе доступа. В частности, тип компонента указанного типа может быть другим типом доступа или даже тем же типом доступа. Это позволяет создавать взаимозависимые и рекурсивные типы доступа. Объявление incomplete_type_declaration может использоваться для введения типа, используемого как указанный тип, откладывая его полное определение до последующего объявления full_type_declaration.
Синтаксис
incomplete_type_declaration ::= type defining_identifier [discriminant_part];
Правила легитимности
Объявление incomplete_type_declaration требует завершения, которое должно быть объявлением full_type_declaration. Если incomplete_type_declaration встречается непосредственно внутри видимой части package_specification или declarative_part, то full_type_declaration должно появиться позже и непосредственно внутри этой видимой части или declarative_part. Если incomplete_type_declaration встречается непосредственно внутри частной части заданного package_specification, то full_type_declaration должно появиться позже и непосредственно внутри либо самой частной части, либо declarative_part соответствующего package_body.
Если incomplete_type_declaration имеет known_discriminant_part, то full_type_declaration, которое его завершает, должно иметь полностью соответствующую (явную) known_discriminant_part (см. 6.3.1). Если incomplete_type_declaration не имеет discriminant_part (или unknown_discriminant_part), то соответствующее full_type_declaration все же может иметь дискриминанты, явным образом или унаследованные через наследование.
Допускается только следующие способы использования имени, обозначающего incomplete_type_declaration:
- как subtype_mark в subtype_indication access_to_object_definition; единственная форма constraint, разрешенная в этой subtype_indication, — это discriminant_constraint;
- как subtype_mark, определяющий подтип параметра или результата access_to_subprogram_definition;
- как subtype_mark в access_definition;
- как prefix attribute_reference, у которого attribute_designator — Class; подобная attribute_reference также ограничена разрешенными здесь способами использования; при использовании таким образом, соответствующее full_type_declaration должно объявлять тип с меткой, а attribute_reference должно находиться в том же модуле, что и incomplete_type_declaration.
Разъяснение (явное или неявное — см. 4.1) не должно относиться к неполному типу.
Статическая семантика
Объявление incomplete_type_declaration объявляет неполный тип и его первый подтип; первый подтип не ограничен, если появляется known_discriminant_part.
Динамическая семантика
Выполнение объявления incomplete_type_declaration не имеет эффекта.
ПРИМЕЧАНИЯ
80 Внутри declarative_part, incomplete_type_declaration и соответствующее full_type_declaration не могут быть разделены промежуточным телом. Это связано с тем, что тип должен быть полностью определён перед его заморозкой, а тело замораживает все типы, объявленные перед ним в той же declarative_part (см. 13.14).
Примеры
Пример рекурсивного типа:
type Cell; -- неполное объявление типа
type Link is access Cell;
type Link is access Cell;
type Cell is
record
Value : Integer;
Succ : Link;
Pred : Link;
end record;
record
Value : Integer;
Succ : Link;
Pred : Link;
end record;
Head : Link := new Cell'(0, null, null);
Next : Link := Head.Succ;
Next : Link := Head.Succ;
Примеры взаимно зависимых типов доступа:
type Person(<>); -- неполное объявление типа
type Car; -- неполное объявление типа
type Car; -- неполное объявление типа
type Person_Name is access Person;
type Car_Name is access all Car;
type Car_Name is access all Car;
type Car is
record
Number : Integer;
Owner : Person_Name;
end record;
record
Number : Integer;
Owner : Person_Name;
end record;
type Person(Sex : Gender) is
record
Name : String(1 .. 20);
Birth : Date;
Age : Integer range 0 .. 130;
Vehicle : Car_Name;
case Sex is
when M => Wife : Person_Name(Sex => F);
when F => Husband : Person_Name(Sex => M);
end case;
end record;
record
Name : String(1 .. 20);
Birth : Date;
Age : Integer range 0 .. 130;
Vehicle : Car_Name;
case Sex is
when M => Wife : Person_Name(Sex => F);
when F => Husband : Person_Name(Sex => M);
end case;
end record;
My_Car, Your_Car, Next_Car : Car_Name := new Car; -- см. 4.8
George : Person_Name := new Person(M);
...
George.Vehicle := Your_Car;
George : Person_Name := new Person(M);
...
George.Vehicle := Your_Car;