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

3.10.1 Неполные объявления типов

Нет особых ограничений на назначенный тип типа доступа. В частности, тип компонента назначенного типа может быть другим типом доступа или даже тем же типом доступа. Это позволяет взаимозависимые и рекурсивные типы доступа. Объявление incomplete_type_declaration может быть использовано для введения типа, используемого в качестве назначенного типа, отложив его полное определение до последующего full_type_declaration.

Синтаксис

incomplete_type_declaration ::= type defining_identifier [discriminant_part] [is tagged];

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

Объявление incomplete_type_declaration объявляет неполный вид типа и его первого подтипа; первый подтип является не ограниченным, если присутствует discriminant_part. Если объявление incomplete_type_declaration включает ключевое слово tagged, оно объявляет меченый неполный вид. Если T обозначает меченый неполный вид, то T'Class обозначает меченый неполный вид. Неполный вид типа — это ограниченный вид типа (см. 7.5).
При заданном типе доступа A, для которого назначенный тип T является неполным видом, разыменование значения типа A также имеет этот неполный вид, за исключением случаев:
  • он встречается в непосредственной области завершения T, или
  • он встречается в области nonlimited_with_clause, которая упоминает библиотечный пакет, в видимой части которого объявлено завершение T, или
  • он встречается в области завершения T, и T является неполным видом, объявленным объявлением incomplete_type_declaration.
В этих случаях разыменование имеет вид T, видимый в момент разыменования.
Аналогично, если subtype_mark обозначает subtype_declaration, определяющий подтип неполного вида T, subtype_mark обозначает неполный вид, за исключением тех же трех случаев, указанных выше, в которых он обозначает вид T, видимый в момент subtype_mark.

Правила законности

Объявление incomplete_type_declaration требует завершения, которое должно быть type_declaration, отличным от incomplete_type_declaration. Если incomplete_type_declaration находится непосредственно внутри видимой части package_specification или declarative_part, то type_declaration должно быть позже и непосредственно внутри этой видимой части или declarative_part. Если incomplete_type_declaration находится непосредственно в частной части заданного package_specification, то type_declaration должно быть позже и непосредственно внутри либо самой частной части, либо declarative_part соответствующего package_body.
Если incomplete_type_declaration включает ключевое слово tagged, то type_declaration, которое его завершает, должно объявлять меченый тип. Если incomplete_type_declaration имеет known_discriminant_part, то type_declaration, которое его завершает, должно иметь полностью соответствующую (явную) known_discriminant_part (см. 6.3.1). Если incomplete_type_declaration не имеет discriminant_part (или unknown_discriminant_part), то соответствующее type_declaration все же может иметь дискриминанты, явно или унаследованные через вывод.
Имя name, которое обозначает неполный вид типа, может использоваться следующим образом:
  • в качестве subtype_mark в subtype_indication access_to_object_definition; единственная форма constraint, разрешенная в этой subtype_indication, это discriminant_constraint (исключение null_exclusion не разрешается);
  • в качестве subtype_mark в subtype_indication subtype_declaration; subtype_indication не должна содержать null_exclusion или constraint;
  • в качестве subtype_mark в access_definition для типа доступа к объекту;
  • в качестве subtype_mark, определяющего подтип параметра или результата в профиле, встречающемся в basic_declaration;
  • как фактический параметр обобщения, соответствующий обобщенному формальному параметру, являющемуся формальным неполным типом (см. 12.5.1).
Если такое имя name обозначает меченый неполный вид, оно также может быть использовано:
  • в качестве subtype_mark, определяющего подтип параметра в профиле для subprogram_body, entry_body или accept_statement;
  • как prefix ссылки на атрибут attribute_reference, у которого attribute_designator — Class; такая ссылка на атрибут ограничена разрешенными здесь использованиями; она обозначает меченый неполный вид.
Этот абзац был удален.
  • Этот абзац был удален.
Если любое из вышеперечисленных применений является частью объявления примитивного подпрограммы неполного вида, и объявление находится непосредственно в частной части пакета, то завершение неполного вида также должно быть непосредственно в частной части; оно не должно откладываться до тела пакета.
Другие использования имени name, обозначающего неполный вид типа, не разрешены.
Префикс prefix, который обозначает объект, не должен быть неполного вида. Фактический параметр в вызове не должен быть немеченым неполным видом. Объект результата вызова функции не должен быть неполного вида. Префикс не должен обозначать подпрограмму, имеющую формальный параметр немеченного неполного вида, а также тип возвращаемого значения — неполный вид.
Абзац 11 был удален.

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

Выполнение объявления incomplete_type_declaration не оказывает никакого влияния.
ПРИМЕЧАНИЯ
89 Внутри declarative_part, incomplete_type_declaration и соответствующая full_type_declaration не могут быть разделены промежуточным блоком. Это связано с тем, что тип должен быть полностью определен перед его заморозкой, а блок замораживает все типы, объявленные перед ним в том же declarative_part (см. 13.14).
90 name, обозначающий объект неполного представления, определяется как тип ограниченного вида. Следовательно, целевой объект оператора присваивания не может быть неполного представления.

Примеры

Пример рекурсивного типа:
type Cell; -- неполное объявление типа
type Link is access Cell;
type Cell is
record
Value : Integer;
Succ : Link;
Pred : Link;
end record;
Head : Link := new Cell'(0, null, null);
Next : Link := Head.Succ;
Примеры взаимно зависимых типов доступа:
type Person(<>); -- неполное объявление типа
type Car is tagged; -- неполное объявление типа
type Person_Name is access Person;
type Car_Name is access all Car'Class;
type Car is tagged
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;
My_Car, Your_Car, Next_Car : Car_Name := new Car; -- см. 4.8
George : Person_Name := new Person(M);
...
George.Vehicle := Your_Car;


Spec-Zone.ru

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