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

3.4 Производные типы и классы

Определение derived_type_definition задаёт производный тип (и его первый подтип), характеристики которого производятся от характеристик родительского типа и, возможно, от типов-предков.
Класс типов — это множество типов, замкнутое относительно производности; то есть, если родительский тип или тип-предок производного типа принадлежит классу, то и производный тип также принадлежит ему. Говоря, что определённая группа типов образует класс, мы подразумеваем, что все производные типа из этого множества наследуют характеристики, определяющие этот класс. Более общее понятие категории типов используется для множества типов, определяющие характеристики которых не обязательно наследуются производными типами; например, ограниченные, абстрактные и интерфейсные типы — это все категории типов, но не классы типов.

Синтаксис

derived_type_definition ::=
[abstract] [limited] new parent_subtype_indication [[and interface_list] record_extension_part]

Правила допустимости

parent_subtype_indication определяет родительский подтип; его тип — это родительский тип. interface_list определяет типы-предков (см. 3.9.4). Производный тип имеет один родительский тип и ноль или более типов-предков.
Тип должен быть полностью определён (см. 3.11.1) до того, как он будет указан в качестве родительского типа в derived_type_definition — объявления full_type_declaration для родительского типа и всех его подкомпонентов должны предшествовать derived_type_definition.
Если есть record_extension_part, производный тип называется расширением записи родительского типа. record_extension_part должен быть указан тогда и только тогда, когда родительский тип является помеченным типом. interface_list должен быть указан только в том случае, если родительский тип является помеченным типом.
Если ключевое слово limited присутствует в derived_type_definition, родительский тип должен быть ограниченным типом. Если родительский тип является формальным помеченным типом, то помимо мест, где обычно применяются правила допустимости (см. 12.3), это правило применяется также в частях с описанием деталей экземпляра (private part) обобщённого блока.

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

Первый подтип производного типа является неограниченным, если в объявлении производного типа указана known_discriminant_part, или если родительский подтип неограничен. В противном случае, ограничение первого подтипа соответствует ограничению родительского подтипа в следующем смысле: оно такое же, как у родительского подтипа, за исключением того, что для ограничения диапазона (явного или неявного) значение каждой границы его диапазона заменяется соответствующим значением производного типа.
Первый подтип производного типа исключает нуль (см. 3.10) тогда и только тогда, когда родительский подтип исключает нуль.
Характеристики и неявные примитивные подпрограммы производного типа определяются следующим образом:
  • Если родительский тип или тип-предок принадлежит классу типов, то производный тип также принадлежит этому классу. Следующие наборы типов, а также любые более высокие множества, составленные из них, являются классами в этом смысле, и поэтому характеристики, определяющие эти классы, наследуются производными типами от их родительского или предкового типов: целые со знаком, модульные целые, обычные фиксированные, десятичные фиксированные, числа с плавающей точкой, перечисления, булевы, символы, доступ к константам, общий доступ к переменной, доступ к переменной, специфичный для пула, доступ к подпрограмме, массив, строка, составной тип, не являющийся массивом, неограниченный, непомеченный тип записи, помеченный, задача, защищённый и синхронизированный помеченный.
  • Если родительский тип является элементарным или массивом, то множество возможных значений производного типа является копией множества возможных значений родительского типа. Для скалярного типа базовый диапазон производного типа такой же, как у родительского типа.
  • Если родительский тип является составным типом, отличным от массива, то компоненты, защищённые подпрограммы и входы, объявленные для производного типа, следующие:
Дискриминанты, заданные новым known_discriminant_part, если таковой имеется; в противном случае каждый дискриминант родительского типа (неявный, объявленный в том же порядке с теми же спецификациями) — в последнем случае дискриминанты называются унаследованными или, если неизвестны в родительском типе, также неизвестны в производном типе;
Каждый компонент, вход и защищённая подпрограмма родительского типа, неявный, объявленный в том же порядке с теми же объявлениями; эти компоненты, входы и защищённые подпрограммы называются унаследованными;
Каждый компонент, объявленный в record_extension_part, если таковой имеется.
Объявления компонентов, защищённых подпрограмм и входов, явные или неявные, находятся непосредственно внутри декларативной области типа в указанном выше порядке, за родительским subtype_indication.
  • Этот абзац был удалён.
  • Для каждого предопределённого оператора родительского типа существует соответствующий предопределённый оператор производного типа.
  • Для каждой пользовательской примитивной подпрограммы (кроме пользовательского оператора равенства — см. ниже) родительского типа или типа-предшественника, который уже существует в месте derived_type_definition, существует соответствующая унаследованная примитивная подпрограмма производного типа с тем же определяющим именем. Примитивные пользовательские операторы равенства родительского типа и всех типов-предшественников также наследуются производным типом, за исключением случаев, когда производный тип является неограниченным расширением записи, а унаследованный оператор имел бы профиль, совместимый с профилем соответствующего предопределённого оператора равенства; в этом случае пользовательский оператор равенства не наследуется, а, скорее, включён в реализацию предопределённого оператора равенства расширения записи (см. 4.5.2).
Профиль унаследованной подпрограммы (включая унаследованную литералу перечисления) получается из профиля соответствующей (пользовательской) примитивной подпрограммы родительского или типа-предшественника после систематической замены каждого подтипа её профиля (см. 6.1), который является типом родителя или предка, отличным от тех подтипов, которые находятся в указанном профиле access_definition, соответствующим подтипом производного типа. Для данного подтипа родительского или предкового типа соответствующий подтип производного типа определяется следующим образом:
Если в объявлении производного типа нет ни known_discriminant_part, ни record_extension_part, то соответствующий подтип имеет ограничение, которое соответствует (как определено выше для первого подтипа производного типа) ограничению данного подтипа.
Если производный тип является расширением записи, то соответствующий подтип является первым подтипом производного типа.
Если производный тип имеет новый known_discriminant_part, но не является расширением записи, то соответствующий подтип ограничен теми значениями, которые при преобразовании в родительский тип принадлежат данному подтипу (см. 4.6).
В профиле унаследованной подпрограммы используются те же формальные параметры, имеющие default_expression. Любой несоответствие типов, вызванное систематической заменой родительского или предкового типа производным типом, обрабатывается как часть обычного преобразования типов, связанного с передачей параметров — см. 6.4.1.
Если примитивная подпрограмма родительского или предкового типа видима в месте derived_type_definition, то соответствующая унаследованная подпрограмма неявно объявляется сразу после derived_type_definition. В противном случае унаследованная подпрограмма неявно объявляется позже или вообще не объявляется, как объяснено в 7.3.1.
Производный тип также может быть определён private_extension_declaration (см. 7.3) или formal_derived_type_definition (см. 12.5.1). Такой производный тип является частичным представлением соответствующего полного или фактического типа.
Все числовые типы являются производными типами, поскольку они неявно производятся от соответствующего корневого числового типа (см. 3.5.4 и 3.5.6).

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

Разработка derived_type_definition создает производный тип и его первый подтип, и состоит из разработки subtype_indication и record_extension_part, если таковые имеются. Если subtype_indication зависит от дискриминанта, то вычисляются только те выражения, которые не зависят от дискриминанта.
Для выполнения вызова унаследованной подпрограммы выполняется вызов соответствующей примитивной подпрограммы родительского или предкового типа; обычная конвертация каждого фактического параметра в подтип соответствующего формального параметра (см. 6.4.1) выполняет также необходимые преобразования типов. Если тип результата унаследованной подпрограммы — это производный тип, результат вызова подпрограммы родительского или предкового типа преобразуется в производный тип, или, в случае нулевого расширения, расширяется до производного типа с помощью эквивалента extension_aggregate со значением исходного результата в качестве ancestor_part и пустого запися как record_component_association_list.
ПРИМЕЧАНИЕ 1 Классы замкнуты относительно производности — любой класс, содержащий тип, также содержит его производные. Операции, доступные для данного класса типов, доступны и для производных типов в этом классе.
ПРИМЕЧАНИЕ 2 Оценка унаследованной перечислительной константы эквивалентна оценке соответствующей перечислительной константы родительского типа, а затем преобразованию результата в производный тип. Это вытекает из их эквивалентности параметризуемым функциям.
ПРИМЕЧАНИЕ 3 Обобщенная подпрограмма не является подпрограммой и, следовательно, не может быть примитивной подпрограммой и не может быть унаследована производным типом. С другой стороны, экземпляр обобщенной подпрограммы может быть примитивной подпрограммой и, следовательно, может быть унаследован.
ПРИМЕЧАНИЕ 4 Если родительский тип — тип доступа, то родительский и производный тип разделяют один и тот же пул памяти; для производного типа существует нулевое значение доступа, и это неявное начальное значение для типа. См. 3.10.
ПРИМЕЧАНИЕ 5 Если родительский тип — булев тип, то предопределенные реляционные операторы производного типа возвращают результат предопределенного типа Boolean (см. 4.5.2). Если родительский тип — целочисленный тип, то правый операнд предопределенного оператора возведения в степень имеет предопределенный тип Integer (см. 4.5.6).
ПРИМЕЧАНИЕ 6 Любые дискриминанты родительского типа либо все унаследованы, либо полностью заменены новым набором дискриминантов.
ПРИМЕЧАНИЕ 7 Для унаследованной подпрограммы подтип формального параметра производного типа может быть таким, что он не имеет общего значения с первым подтипом производного типа.
ПРИМЕЧАНИЕ 8 Если в объявлении типа указано ключевое слово abstract, то тип является абстрактным (см. 3.9.3).
ПРИМЕЧАНИЕ 9 Тип интерфейса, имеющий предковый тип "производится из" этого типа. Однако derived_type_definition никогда не определяет тип интерфейса.
ПРИМЕЧАНИЕ 10 Недопустимо, чтобы родительский тип derived_type_definition был синхронизированным помеченным типом.

Примеры

Примеры объявлений производных типов:
type Local_Coordinate is new Coordinate; -- два разных типа
type Midweek is new Day range Tue .. Thu; -- см. 3.5.1
type Counter is new Positive; -- тот же диапазон, что и Positive
type Special_Key is new Key_Manager.Key; -- см. 7.3.1
-- унаследованные подпрограммы имеют следующие спецификации:
-- procedure Get_Key(K : out Special_Key);
-- function "<"(X,Y : Special_Key) return Boolean;


Spec-Zone.ru

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