3.4 Derived Types and Classes
A 
derived_type_definition 
defines a 
derived type (and its first subtype) whose characteristics 
are 
derived from those of a parent type, and possibly from progenitor 
types. 
 
  A 
class 
of types is a set of types that is closed under derivation; that 
is, if the parent or a progenitor type of a derived type belongs to a 
class, then so does the derived type. By saying that a particular group 
of types forms a class, we are saying that all derivatives of a type 
in the set inherit the characteristics that define that set. The more 
general term 
category of types is used for a set of types whose 
defining characteristics are not necessarily inherited by derivatives; 
for example, limited, abstract, and interface are all categories of types, 
but not classes of types.
 
Syntax
Legality Rules
The 
parent_subtype_indication 
defines the 
parent subtype; its type is the 
parent type. 
The 
interface_list 
defines the progenitor types (see 
3.9.4). 
A derived type has one parent type and zero or more progenitor types.
 
  If the reserved word 
limited appears in 
a 
derived_type_definition, 
the parent type shall be a limited type. If the parent type is a tagged 
formal type, then in addition to the places where Legality Rules normally 
apply (see 
12.3), this rule applies also in 
the private part of an instance of a generic unit.
 
 
Static Semantics
The first 
subtype of the derived type is unconstrained if a 
known_discriminant_part 
is provided in the declaration of the derived type, or if the parent 
subtype is unconstrained. 
Otherwise, the constraint 
of the first subtype 
corresponds to that of the parent subtype 
in the following sense: it is the same as that of the parent subtype 
except that for a range constraint (implicit or explicit), the value 
of each bound of its range is replaced by the corresponding value of 
the derived type. 
 
  The first subtype of the derived type excludes 
null (see 
3.10) if and only if the parent 
subtype excludes null.
 
The 
characteristics 
and implicitly declared primitive subprograms of the derived type are 
defined as follows: 
 
If the parent type or a progenitor type belongs 
to a class of types, then the derived type also belongs to that class. 
The following sets of types, as well as any higher-level sets composed 
from them, are classes in this sense, and hence the characteristics defining 
these classes are inherited by derived types from their parent or progenitor 
types: signed integer, modular integer, ordinary fixed, decimal fixed, 
floating point, enumeration, boolean, character, access-to-constant, 
general access-to-variable, pool-specific access-to-variable, access-to-subprogram, 
array, string, non-array composite, nonlimited, untagged record, tagged, 
task, protected, and synchronized tagged. 
If the parent type is an elementary type or an 
array type, then the set of possible values of the derived type is a 
copy of the set of possible values of the parent type. For a scalar type, 
the base range of the derived type is the same as that of the parent 
type. 
If the parent type is a composite type other than 
an array type, then the components, protected subprograms, and entries 
that are declared for the derived type are as follows: 
The discriminants specified by a 
new 
known_discriminant_part, 
if there is one; otherwise, each discriminant of the parent type (implicitly 
declared in the same order with the same specifications) — 
in 
the latter case, the discriminants are said to be 
inherited, or 
if unknown in the parent, are also unknown in the derived type;
 
Each nondiscriminant component, 
entry, and protected subprogram of the parent type, implicitly declared 
in the same order with the same declarations; 
these 
components, entries, and protected subprograms are said to be 
inherited; 
 
Declarations of components, protected 
subprograms, and entries, whether implicit or explicit, occur immediately 
within the declarative region of the type, in the order indicated above, 
following the parent 
subtype_indication. 
 
This paragraph 
was deleted.
For each predefined operator of the parent type, 
there is a corresponding predefined operator of the derived type. 
For each user-defined primitive 
subprogram (other than a user-defined equality operator — see below) 
of the parent type or of a progenitor type that already exists at the 
place of the 
derived_type_definition, 
there exists a corresponding 
inherited primitive subprogram of 
the derived type with the same defining name. 
Primitive 
user-defined equality operators of the parent type and any progenitor 
types are also inherited by the derived type, except when the derived 
type is a nonlimited record extension, and the inherited operator would 
have a profile that is type conformant with the profile of the corresponding 
predefined equality operator; in this case, the user-defined equality 
operator is not inherited, but is rather incorporated into the implementation 
of the predefined equality operator of the record extension (see 
4.5.2). 
 
The profile of an inherited subprogram 
(including an inherited enumeration literal) is obtained from the profile 
of the corresponding (user-defined) primitive subprogram of the parent 
or progenitor type, after systematic replacement of each subtype of its 
profile (see 
6.1) that is of the parent or 
progenitor type, other than those subtypes found in the designated profile 
of an 
access_definition, 
with a 
corresponding subtype of the derived type. 
For 
a given subtype of the parent or progenitor type, the corresponding subtype 
of the derived type is defined as follows: 
 
If the declaration of the derived 
type has neither a 
known_discriminant_part 
nor a 
record_extension_part, 
then the corresponding subtype has a constraint that corresponds (as 
defined above for the first subtype of the derived type) to that of the 
given subtype.
 
If the derived type is a record 
extension, then the corresponding subtype is the first subtype of the 
derived type.
If the derived type has a new 
known_discriminant_part 
but is not a record extension, then the corresponding subtype is constrained 
to those values that when converted to the parent type belong to the 
given subtype (see 
4.6). 
 
The same formal parameters have 
default_expressions 
in the profile of the inherited subprogram. Any type mismatch due to 
the systematic replacement of the parent or progenitor type by the derived 
type is handled as part of the normal type conversion associated with 
parameter passing — see 
6.4.1. 
 
 If a primitive subprogram of the parent or progenitor 
type is visible at the place of the 
derived_type_definition, 
then the corresponding inherited subprogram is implicitly declared immediately 
after the 
derived_type_definition. 
Otherwise, the inherited subprogram is implicitly declared later or not 
at all, as explained in 
7.3.1.
 
All numeric types are derived types, in that they 
are implicitly derived from a corresponding root numeric type (see 
3.5.4 
and 
3.5.6).
 
Dynamic Semantics
 For the execution of a call 
on an inherited subprogram, a call on the corresponding primitive subprogram 
of the parent or progenitor type is performed; the normal conversion 
of each actual parameter to the subtype of the corresponding formal parameter 
(see 
6.4.1) performs any necessary type conversion 
as well. If the result type of the inherited subprogram is the derived 
type, the result of calling the subprogram of the parent or progenitor 
is converted to the derived type, or in the case of a null extension, 
extended to the derived type using the equivalent of an 
extension_aggregate 
with the original result as the 
ancestor_part 
and 
null record as the 
record_component_association_list. 
 
16  
Classes are closed 
under derivation — any class that contains a type also contains 
its derivatives. Operations available for a given class of types are 
available for the derived types in that class.
 
17  Evaluating an inherited enumeration 
literal is equivalent to evaluating the corresponding enumeration literal 
of the parent type, and then converting the result to the derived type. 
This follows from their equivalence to parameterless functions. 
 
18  A generic subprogram is not a subprogram, 
and hence cannot be a primitive subprogram and cannot be inherited by 
a derived type. On the other hand, an instance of a generic subprogram 
can be a primitive subprogram, and hence can be inherited.
19  If the parent type is an access type, 
then the parent and the derived type share the same storage pool; there 
is a 
null access value for the derived type and it is the implicit 
initial value for the type. See 
3.10.
 
20  If the parent type is a boolean type, 
the predefined relational operators of the derived type deliver a result 
of the predefined type Boolean (see 
4.5.2). 
If the parent type is an integer type, the right operand of the predefined 
exponentiation operator is of the predefined type Integer (see 
4.5.6).
 
21  Any discriminants of the parent type 
are either all inherited, or completely replaced with a new set of discriminants.
22  For an inherited subprogram, the subtype 
of a formal parameter of the derived type need not have any value in 
common with the first subtype of the derived type. 
23  If the reserved word 
abstract 
is given in the declaration of a type, the type is abstract (see 
3.9.3).
 
24  An interface type that has a progenitor 
type “is derived from” that type. A 
derived_type_definition, 
however, never defines an interface type.
 
Examples
Examples of derived 
type declarations: 
type Local_Coordinate 
is new Coordinate;   --
  two different types
type Midweek 
is new Day 
range Tue .. Thu;  --
  see 3.5.1
type Counter 
is new Positive;              --
  same range as Positive  
type Special_Key 
is new Key_Manager.Key;   --
  see 7.3.1
  --
 the inherited subprograms have the following specifications: 
  --
         procedure Get_Key(K : out Special_Key);
  --
         function "<"(X,Y : Special_Key) return Boolean; 
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe