3.4.1 Derivation Classes
In addition to the various language-defined classes 
of types, types can be grouped into derivation classes. 
Static Semantics
A derived type is 
derived 
from its parent type 
directly; it is derived 
indirectly 
from any type from which its parent type is derived. A derived type, 
interface type, type extension, task type, protected type, or formal 
derived type is also derived from every ancestor of each of its progenitor 
types, if any. 
The 
derivation class of types for a type 
T (also called the class 
rooted at 
T) is the set consisting of 
T (the 
root 
type of the class) and all types derived from 
T (directly 
or indirectly) plus any associated universal or class-wide types (defined 
below). 
 
Every type is either a 
specific type, a 
class-wide 
type, or a 
universal type. 
A specific type 
is one defined by a 
type_declaration, 
a 
formal_type_declaration, 
or a full type definition embedded in another construct. Class-wide and 
universal types are implicitly defined, to act as representatives for 
an entire class of types, as follows: 
 
Class-wide types are defined for (and belong to) each derivation class 
rooted at a tagged type (see 
3.9). Given a 
subtype S of a tagged type 
T, S'Class is the 
subtype_mark 
for a corresponding subtype of the tagged class-wide type 
T'Class. 
Such types are called “class-wide” because when a formal 
parameter is defined to be of a class-wide type 
T'Class, an actual 
parameter of any type in the derivation class rooted at 
T is acceptable 
(see 
8.6).
 
The set of values for 
a class-wide type 
T'Class is the discriminated union of the set 
of values of each specific type in the derivation class rooted at 
T 
(the tag acts as the implicit discriminant — see 
3.9). 
Class-wide types have no primitive subprograms of their own. However, 
as explained in 
3.9.2, operands of a class-wide 
type 
T'Class can be used as part of a dispatching call on a primitive 
subprogram of the type 
T. The only components (including discriminants) 
of 
T'Class that are visible are those of 
T. If S is a first 
subtype, then S'Class is a first subtype. 
 
Universal types are defined for (and belong to) the integer, real, fixed 
point, and access classes, and are referred to in this standard as respectively, 
universal_integer, 
universal_real, 
universal_fixed, 
and 
universal_access. 
These are analogous to class-wide types for these language-defined elementary 
classes. As with class-wide types, if a formal parameter is of a universal 
type, then an actual parameter of any type in the corresponding class 
is acceptable. In addition, a value of a universal type (including an 
integer or real 
numeric_literal, 
or the literal 
null) is “universal” in that it is 
acceptable where some particular type in the class is expected (see 
8.6).
 
The set of values of a universal type is 
the undiscriminated union of the set of values possible for any definable 
type in the associated class. Like class-wide types, universal types 
have no primitive subprograms of their own. However, their “universality” 
allows them to be used as operands with the primitive subprograms of 
any type in the corresponding class. 
The integer 
and real numeric classes each have a specific root type in addition to 
their universal type, named respectively 
root_integer and 
root_real.
 
A class-wide or universal type 
is said to 
cover all of the types in its class. A specific type 
covers only itself.
 
 A specific type 
T2 is 
defined to be a 
descendant of a type 
T1 if 
T2 is 
the same as 
T1, or if 
T2 is derived (directly or indirectly) 
from 
T1. A class-wide type 
T2'Class is defined to be a 
descendant of type 
T1 if 
T2 is a descendant of 
T1. 
Similarly, the numeric universal types are defined to be descendants 
of the root types of their classes. 
If a type 
T2 
is a descendant of a type 
T1, then 
T1 is called an 
ancestor 
of 
T2. 
An 
ultimate 
ancestor of a type is an ancestor of that type that is not itself 
a descendant of any other type. Every untagged type has a unique ultimate 
ancestor. 
 
An inherited component (including 
an inherited discriminant) of a derived type is inherited 
from 
a given ancestor of the type if the corresponding component was inherited 
by each derived type in the chain of derivations going back to the given 
ancestor.
 
26  Because operands of a universal type 
are acceptable to the predefined operators of any type in their class, 
ambiguity can result. For 
universal_integer and 
universal_real, 
this potential ambiguity is resolved by giving a preference (see 
8.6) 
to the predefined operators of the corresponding root types (
root_integer 
and 
root_real, respectively). Hence, in an apparently ambiguous 
expression like 
 
1 + 4 < 7
where each of the literals is of type universal_integer, 
the predefined operators of root_integer will be preferred over 
those of other specific integer types, thereby resolving the ambiguity. 
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe