Справочник по Ada 2012
3.4.1 Классы производных типов
Помимо различных определенных языком классов типов, типы могут быть сгруппированы в классы производных типов.
Статическая семантика
Производный тип производится от своего родительского типа непосредственно; он производятся косвенно от любого типа, от которого производятся его родительский тип. Производный тип, интерфейсный тип, расширение типа, тип задачи, защищённый тип или формальный производный тип также производятся от каждого предка каждого из его типов-предков, если таковые имеются. Класс производных типов для типа T (также называемый классом, основанным на T) — это множество, состоящее из T (корневого типа класса) и всех типов, производных от T (прямо или косвенно), плюс любые ассоциированные универсальные или классовые типы (определены ниже).
Каждый тип является либо специфическим типом, либо типом класса, либо универсальным типом. Специфический тип определяется с помощью type_declaration, formal_type_declaration или полным определением типа, встроенным в другую конструкцию. Типы класса и универсальные типы неявно определяются для представления целого класса типов следующим образом:
Типы класса
Типы класса определены для (и принадлежат) каждому классу производных типов, укоренённому в типе с меткой (см. 3.9). Учитывая подтип S типа с меткой T, S'Class — это subtype_mark для соответствующего подтипа типа класса с меткой T'Class. Такие типы называются «типами класса», потому что, когда формальный параметр определён как типа класса T'Class, допустим фактический параметр любого типа в классе производных типов, укоренённом в T (см. 8.6).
Множество значений для типа класса T'Class — это дискриминируемое объединение множества значений каждого специфического типа в классе производных типов, укоренённом в T (метка выступает в качестве неявного дискриминанта — см. 3.9). Типы класса не имеют собственных примитивных подпрограмм. Однако, как поясняется в 3.9.2, операнды типа класса T'Class могут использоваться в качестве части вызова подпрограммы с диспетчеризацией для примитивной подпрограммы типа T. Единственными компонентами (включая дискриминанты) T'Class, которые видны, являются те, что принадлежат T. Если S — это подтип первого порядка, то S'Class — это подтип первого порядка.
Универсальные типы
Универсальные типы определены для (и принадлежат) целым, вещественным, фиксированным и доступным классам и в этом стандарте обозначаются соответственно как universal_integer, universal_real, universal_fixed и universal_access. Они аналогичны типам класса для этих определённых языком элементарных классов. Как и в случае с типами класса, если формальный параметр имеет универсальный тип, то фактический параметр любого типа в соответствующем классе приемлем. Кроме того, значение универсального типа (включая целое или вещественное numeric_literal или литерал null) является «универсальным» в том смысле, что он приемлем там, где ожидается какой-то конкретный тип в классе (см. 8.6).
Множество значений универсального типа — это объединение множества значений, возможных для любого определяемого типа в ассоциированном классе. Как и типы класса, универсальные типы не имеют собственных примитивных подпрограмм. Однако их «универсальность» позволяет использовать их в качестве операндов с примитивными подпрограммами любого типа в соответствующем классе.
Классы целых и вещественных чисел каждый имеют специфический корневой тип в дополнение к своему универсальному типу, называемый соответственно root_integer и root_real.
Тип класса или универсальный тип называется покрывающим все типы в своём классе. Специфический тип покрывает только себя.
Специфический тип T2 определён как потомок типа T1, если T2 совпадает с T1, или если T2 произведён (прямо или косвенно) от T1. Тип класса T2'Class определяется как потомок типа T1, если T2 является потомком T1. Аналогично, универсальные числовые типы определены как потомки корневых типов их классов. Если тип T2 является потомком типа T1, то T1 называется предком T2. Конечный предок типа — это предок этого типа, который сам не является потомком любого другого типа. Каждый немеченый тип имеет уникального конечного предка.
Наследуемый компонент (включая наследуемый дискриминант) производного типа наследуется от данного предка типа, если соответствующий компонент был унаследован каждым производным типом в цепи производных, ведущей к данному предку.
ПРИМЕЧАНИЯ
26 Поскольку операнды универсального типа приемлемы для предопределённых операторов любого типа в их классе, может возникнуть неоднозначность. Для universal_integer и universal_real эта потенциальная неоднозначность разрешается путём предпочтения (см. 8.6) предопределённых операторов соответствующих корневых типов (root_integer и root_real соответственно). Таким образом, в, по-видимому, неоднозначном выражении, таком как
1 + 4 < 7
где каждый из литералов имеет тип universal_integer, будут отданы предпочтения предопределённые операторы root_integer перед операторами других конкретных целых типов, тем самым разрешая неоднозначность.