A *type*
is characterized by a set of values, and a set of *primitive operations*
which implement the fundamental aspects of its semantics. An
*object* of a given type is a run-time entity that contains (has)
a value of the type.

Types are
grouped into *categories* of types. There exist
several *language-defined categories* of types (see NOTES below),
reflecting the similarity of their values and primitive operations.
Most categories of types form *classes* of types. *Elementary*
types are those whose values are logically indivisible; *composite*
types are those whose values are composed of *component* values.

The elementary types are the
*scalar* types (*discrete* and *real*) and the *access*
types (whose values provide access to objects or subprograms). Discrete
types are either *integer* types or are defined by enumeration of
their values (*enumeration* types). Real types
are either *floating point* types or *fixed point* types.

The composite types are the *record* types,
*record extensions*, *array* types, *interface* types,
*task* types, and *protected* types.

There
can be multiple views of a type with varying sets of operations. An *incomplete*
type represents an incomplete view (see 3.10.1)
of a type with a very restricted usage, providing support for recursive
data structures. A *private* type or *private extension* represents
a partial view (see 7.3) of a type, providing
support for data abstraction. The full view (see 3.2.1)
of a type represents its complete definition. An incomplete or partial
view is considered a composite type, even if the full view is not.

Certain composite types (and
views thereof) have special components called *discriminants* whose
values affect the presence, constraints, or initialization of other components.
Discriminants can be thought of as parameters of the type.

The term *subcomponent*
is used in this International Standard in place of the term component
to indicate either a component, or a component of another subcomponent.
Where other subcomponents are excluded, the term component is used instead.
Similarly, a *part* of an object or value is
used to mean the whole object or value, or any set of its subcomponents.
The terms component, subcomponent, and part are also applied to a type
meaning the component, subcomponent, or part of objects and values of
the type.

The set of possible values for
an object of a given type can be subjected to a condition that is called
a *constraint* (the case
of a *null constraint* that specifies no restriction is also included);
the rules for which values satisfy a given kind of constraint are given
in 3.5 for range_constraints,
3.6.1 for index_constraints,
and 3.7.1 for discriminant_constraints.
The set of possible values for an object of an access type can also be
subjected to a condition that excludes the null value (see 3.10).

A *subtype* of a given type
is a combination of the type, a constraint on values of the type, and
certain attributes specific to the subtype. The given type is called
the *type of the subtype*. Similarly,
the associated constraint is called the *constraint of the subtype*.
The set of values of a subtype consists of the values
of its type that satisfy its constraint and any exclusion of the null
value. Such values *belong* to the subtype.

A
subtype is called an *unconstrained* subtype if its type has unknown
discriminants, or if its type allows range, index, or discriminant constraints,
but the subtype does not impose such a constraint; otherwise, the subtype
is called a *constrained* subtype (since it has no unconstrained
characteristics).

NOTES

2 Any set of types can be called a “category”
of types, and any set of types that is closed under derivation (see 3.4)
can be called a “class” of types. However, only certain categories
and classes are used in the description of the rules of the language
— generally those that have their own particular set of primitive
operations (see 3.2.3), or that correspond
to a set of types that are matched by a given kind of generic formal
type (see 12.5). The following
are examples of “interesting” *language-defined classes*:
elementary, scalar, discrete, enumeration, character, boolean, integer,
signed integer, modular, real, floating point, fixed point, ordinary
fixed point, decimal fixed point, numeric, access, access-to-object,
access-to-subprogram, composite, array, string, (untagged) record, tagged,
task, protected, nonlimited. Special syntax is provided to define types
in each of these classes. In addition to these classes, the following
are examples of “interesting” *language-defined categories*:
abstract, incomplete, interface, limited, private,
record.

These language-defined categories are organized like
this:

all types

elementary

scalar

discrete

enumeration

character

boolean

other enumeration

integer

signed integer

modular integer

real

floating point

fixed point

ordinary fixed point

decimal fixed point

access

access-to-object

access-to-subprogram

composite

untagged

array

string

other array

record

task

protected

tagged (including interfaces)

nonlimited tagged record

limited tagged

limited tagged record

synchronized tagged

tagged task

tagged protected

elementary

scalar

discrete

enumeration

character

boolean

other enumeration

integer

signed integer

modular integer

real

floating point

fixed point

ordinary fixed point

decimal fixed point

access

access-to-object

access-to-subprogram

composite

untagged

array

string

other array

record

task

protected

tagged (including interfaces)

nonlimited tagged record

limited tagged

limited tagged record

synchronized tagged

tagged task

tagged protected

There are other categories, such as “numeric”
and “discriminated”, which represent other categorization
dimensions, but do not fit into the above strictly hierarchical picture.

Ada 2005 and 2012 Editions sponsored in part by **Ada-Europe**