Contents Index Search Previous Next

1

In addition to the various language-defined classes
of types, types can be grouped into *derivation classes*.

2

{*derived from (directly or
indirectly)*} A derived type is *derived
from* its parent type *directly*; it is derived *indirectly*
from any type from which its parent type is derived. {*derivation
class (for a type)*} {*root
type (of a class)*} {*rooted
at a type*} 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).

2.a

2.b

3

Every type is either a *specific* type, a
*class-wide* type, or a *universal* type. {*specific
type*} A specific type is one defined by
a type_declaration, a formal_type_declaration,
or a full type definition embedded in a declaration for an object. Class-wide
and universal types are implicitly defined, to act as representatives
for an entire class of types, as follows:

3.a

4

- {
*class-wide type*} Class-wide types -
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).

5

- {
*first subtype*} 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.

5.a

6

- {
*universal type*} Universal types -
Universal types are defined for [(and belong to)] the integer, real,
and fixed point classes, and are referred to in this standard as respectively,
*universal_integer*,*universal_real*, and*universal_fixed*. These are analogous to class-wide types for these language-defined numeric 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) is ``universal'' in that it is acceptable where some particular type in the class is expected (see 8.6).

7

- 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.

7.a

7.b

We considered defining class-wide
or perhaps universal types for all derivation classes, not just tagged
classes and these three numeric classes. However, this was felt to overly
weaken the strong-typing model in some situations. Tagged types preserve
strong type distinctions thanks to the run-time tag. Class-wide or universal
types for untagged types would weaken the compile-time type distinctions
without providing a compensating run-time-checkable distinction.

7.c

We considered defining standard
names for the universal numeric types so they could be used in formal
parameter specifications. However, this was felt to impose an undue implementation
burden for some implementations.

7.d

8

{*root_integer* [partial]}
{*root_real* [partial]}
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*.

9

{*cover (a type)*}
A class-wide or universal type is said to *cover*
all of the types in its class. A specific type covers only itself.

10

{*descendant (of a type)*}
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 universal types are defined
to be descendants of the root types of their classes. {*ancestor
(of a type)*} If a type *T2* is a
descendant of a type *T1*, then *T1* is called an *ancestor*
of *T2*. {*ultimate ancestor (of a type)*}
{*ancestor (ultimate)*}
The *ultimate ancestor* of a type is the ancestor
of the type that is not a descendant of any other type.

10.a

10.b

A specific type is an ancestor
of itself. The root of a derivation class is an ancestor of all types
in the class, including any class-wide types in the class.

10.c

10.d

- Each type has at most one parent, and one or more ancestor types; each type has exactly one ultimate ancestor. In Ada 83, the term ``parent type'' was sometimes used more generally to include any ancestor type (e.g. RM83-9.4(14)). In Ada 95, we restrict parent to mean the immediate ancestor.

10.e

- A class of types has at most one root type; a derivation class has exactly one root type.

10.f

- The root of a class is an ancestor of all of the types in the class (including itself).

10.g

- The type
*root_integer*is the root of the integer class, and is the ultimate ancestor of all integer types. A similar statement applies to*root_real*.

11

{*inherited (from an ancestor
type)*} 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.

NOTES

12

18 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

13

1 + 4 < 7

14

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.

14.a