# Ada Programming/Object Orientation

## Object orientation in Ada

Object oriented programming consists in building the software in terms
of \"objects\". An \"object\" contains data and has a behavior. The
data, normally, consists in constants and variables as seen in the rest
of this book but could also, conceivably, reside outside the program
entirely, i.e. on disk or on the network. The behavior consists in
subprograms that operate on the data. What makes Object Orientation
unique, compared to procedural programming, is not a single feature but
the combination of several features:

-   *encapsulation*, i.e. the ability to separate the implementation of
    an object from its interface; this in turn separates \"clients\" of
    the object, who can only use the object in certain predefined ways,
    from the internals of the object, which have no knowledge of the
    outside clients.

```{=html}
<!-- -->
```
-   *inheritance*, the ability for one type of objects to inherit the
    data and behavior (subprograms) of another, without necessarily
    needing to break encapsulation;

```{=html}
<!-- -->
```
-   *type extension*, the ability for an object to add new data
    components and new subprograms on top of the inherited ones and to
    *replace* some inherited subprograms with its own versions; this is
    called *overriding*.

```{=html}
<!-- -->
```
-   *polymorphism*, the ability for a \"client\" to use the services of
    an object without knowing the exact type of the object, i.e. in an
    abstract way. Indeed at run time, the actual objects can have
    different types from one invocation to the next.

It is possible to do object-oriented programming in any language, even
assembly. However, type extension and polymorphism are very difficult to
get right without language support.

In Ada, each of these concepts has a matching construct; this is why Ada
supports object-oriented programming directly.

-   Packages provide encapsulation;
-   Derived types provide inheritance;
-   Record extensions, described below, provide for type extension;
-   Class-wide types, also described below, provide for polymorphism.

Ada has had encapsulation and derived types since the first version
(MIL-STD-1815 in 1980), which led some to qualify the language as
\"object-oriented\" in a very narrow sense. Record extensions and
class-wide types were added in Ada 95. Ada 2005 further adds interfaces.
The rest of this chapter covers these aspects.

### The simplest object: the Singleton

` Directory `\
`  `` Present (Name_Pattern: String) `` Boolean;`\
`  `\
`     `` Visit (Full_Name, Phone_Number, Address: String;`\
`                           Stop: `` Boolean);`\
`  `` Iterate (Name_Pattern: String);`\
` Directory;`

The Directory is an object consisting of data (the telephone numbers and
addresses, presumably held in an external file or database) and behavior
(it can look an entry up and traverse all the entries matching a
Name_Pattern, calling Visit on each).

A simple package provides for encapsulation (the inner workings of the
directory are hidden) and a pair of subprograms provide the behavior.

This pattern is appropriate when only one object of a certain type must
exist; there is, therefore, no need for type extension or polymorphism.

### Primitive operations

In Ada, methods are usually referred to by the technical term *primitive
subprograms of a tagged type* or the equivalent term *primitive
operations of a tagged type*. The primitive operations of a type are
those that are always available wherever the type is used. For the
tagged types that are used in object oriented programming, they also can
be inherited by and overridden by derived types, and can be dynamically
dispatched.

Primitive operations of a type need to be declared immediately within
the same package as the type (not within a nested package nor a child
package). For tagged types, new primitive operations and overrides of
inherited primitive operations are further required to be declared
before the *freezing point* of the type. Any subprograms declared after
the freezing point will not be considered primitive, and therefore
cannot be inherited and are not dynamically dispatched. Freezing points
are discussed in more detail below, but the simple practice of declaring
all primitive operations immediately following the initial type
declaration will ensure that those subprograms are indeed recognized as
primitive.

Primitive operations of type T need to have at least one parameter of
type `T` or of type `access T`. While most object-oriented languages
automatically provide a `this` or `self` pointer, Ada requires that you
explicitly declare a formal parameter to receive the current object.
That typically will be the first parameter in the list, which enables
the `object.subprogram` call syntax (available since Ada 2005), but it
may be at any parameter position. Tagged types are always passed by
reference; the parameter passing method has nothing to do with the
parameter modes `in` and `out`, which describe the dataflow. The
parameter passing method is identical for `T` and `access T`.

For tagged types, no other directly dispatchable types can be used in
the parameter list because Ada doesn\'t offer multiple dispatching. The
following example is illegal.

` P `\
`   `` A `` `` ``;`\
`   `` B `` `` ``;`\
`   `` Proc (This: B; That: A); `\
` P;`

When additional dispatchable objects need to be passed in, the parameter
list should declare them using their class-wide types, `T'Class`. For
example:

` P `\
`   `` A `` `` ``;`\
`   `` B `` `` ``;`\
`   `` Proc (This: B; That: A'Class); `\
` P;`

Note, however, that this does not limit the number of parameters of the
same tagged type. For example, the following definition is legal.

` P `\
`   `` A `` `` ``;`\
`   `` Proc (This, That: A); `\
` P;`

Primitive operations of tagged types are dispatching operations. Whether
a call to such a primitive operation is in effect dispatching or
statically bound, depends on the context (see below). Note that in a
dispatching call both actual parameters of the last example must have
the same tag (i.e. the same type); Constraint_Error will be called if
the tag check fails.

### Derived types

Type derivation has been part of Ada since the very start.

` P `\
`  `` T ``;`\
`  `` Create (Data: Boolean) `` T;  `\
`  `` Work (Object : `` T);        `\
`  `` Work (Pointer: `` T);        `\
`  `` Acc_T `` T;`\
`  `` Proc (Pointer: Acc_T);           `\
\
`  `` T `\
`    Data: Boolean;`\
`  ``;`\
` P;`

The above example creates a type T that contains data (here just a
Boolean but it could be anything) and behavior consisting of some
subprograms. It also demonstrates encapsulation by placing the details
of the type T in the private part of the package.

The primitive operations of T are the function Create, the overloaded
procedures Work, and the predefined \"=\" operator; Proc is not
primitive, since it has an *access type* on T as parameter --- don\'t
confuse this with an *access parameter*, as used in the second procedure
Work. When deriving from T, the primitive operations are inherited.

` P;`\
` Q `\
`  `` Derived `` P.T;`\
` Q;`

The type Q.Derived has the same data *and the same behavior* as P.T; it
inherits both the data *and the subprograms*. Thus it is possible to
write:

` Q;`\
` Main `\
`  Object: Q.Derived := Q.Create (Data => False);`\
\
`  Q.Work (Object);`\
` Main;`

Inherited operations may be overridden and new operations added, but the
rules (Ada 83) unfortunaltely are somewhat different from the rules for
tagged types (Ada 95).

Admittedly, the reasons for writing this may seem obscure. The purpose
of this kind of code is to have objects of types P.T and Q.Derived,
which are not compatible:

`Ob1: P.T;`\
`Ob2: Q.Derived;`

`Ob1 := Ob2;              -- illegal`\
`Ob1 := P.T (Ob2);        -- but convertible`\
`Ob2 := Q.Derived (Ob1);  -- in both directions`

This feature is not used very often (it\'s used e.g. for declaring types
reflecting physical dimensions) but I present it here to introduce the
next step: type extension.

### Type extensions

Type extensions are an Ada 95 amendment.

A tagged type provides support for dynamic polymorphism and type
extension. A tagged type bears a hidden tag that identifies the type at
run-time. Apart from the tag, a tagged record is like any other record,
so it can contain arbitrary data.

` Person `\
`   `` Object `` `\
`     `\
`         Name   : String (1 .. 10);`\
`         Gender : Gender_Type;`\
`     `` ``;`\
`   `` Put (O : Object);`\
` Person;`

As you can see, a `Person.Object` is an *object* in the sense that it
has data and behavior (the procedure `Put`). However, this object does
not hide its data; any program unit that has a
` Person` clause can read and write the
data in a Person.Object directly. This breaks encapsulation and also
illustrates that Ada completely separates the concepts of
*encapsulation* and *type*. Here is a version of Person.Object that
encapsulates its data:

` Person `\
`   `` Object `` ``;`\
`   `` Put (O : Object);`\
\
`   `` Object `` `\
`     `\
`         Name   : String (1 .. 10);`\
`         Gender : Gender_Type;`\
`     `` ``;`\
` Person;`

Because the type Person.Object is tagged, it is possible to create a
record extension, which is a derived type with additional data.

` Person;`\
` Programmer `\
`   `` Object `` `` Person.Object ``;`\
\
`   `` Object `` `` Person.Object `\
`     `\
`        Skilled_In : Language_List;`\
`     `` ``;`\
` Programmer;`

The type `Programmer.Object` inherits the data and behavior, i.e. the
type\'s primitive operations, from `Person.Object`; it is thus possible
to write:

` Programmer;`\
` Main `\
`   Me : Programmer.Object;`\
\
`   Programmer.Put (Me);`\
`   Me.Put; `\
` Main;`

So the declaration of the type `Programmer.Object`, as a record
extension of `Person.Object`, implicitly declares a
` Put` that applies to a
`Programmer.Object`.

Like in the case of untagged types, objects of type Person and
Programmer are convertible. However, where untagged objects are
convertible in either direction, conversion of tagged types only works
in the direction to the root. (Conversion away from the root would have
to add components out of the blue.) Such a conversion is called a *view
conversion*, because components are not lost, they only become
invisible.

Extension aggregates have to be used if you go away from the root.

### Overriding

Now that we have introduced tagged types, record extensions and
primitive operations, it becomes possible to understand overriding. In
the examples above, we introduced a type `Person.Object` with a
primitive operation called `Put`. Here is the body of the package:

` Ada.Text_IO;`\
` Person `\
`   `` Put (O : Object) `\
`   `\
`      Ada.Text_IO.Put (O.Name);`\
`      Ada.Text_IO.Put (" is a ");`\
`      Ada.Text_IO.Put_Line (Gender_Type'Image (O.Gender));`\
`   `` Put;`\
` Person;`

As you can see, this simple operation prints both data components of the
record type to standard output. Now, remember that the record extension
`Programmer.Object` has an additional data member. If we write:

` Programmer;`\
` Main `\
`   Me : Programmer.Object;`\
\
`   Programmer.Put (Me);`\
`   Me.Put; `\
` Main;`

then the program will call the inherited primitive operation `Put`,
which will print the name and gender *but not the additional data*. In
order to provide this extra behavior, we must *override* the inherited
procedure `Put` like this:

` Person;`\
` Programmer `\
`   `` Object `` `` Person.Object ``;`\
`   `` `\
`   `` Put (O : Object);`\
\
`   `` Object `` `` Person.Object `\
`     `\
`        Skilled_In : Language_List;`\
`     `` ``;`\
` Programmer;`

` Programmer `\
`   `` Put (O : Object) `\
`   `\
`      Person.Put (Person.Object (O)); `\
`      Put (O.Skilled_In); `\
`   `` Put;`\
` Programmer;`

`Programmer.Put` *overrides* `Person.Put`; in other words it *replaces*
it completely. Since the intent is to extend the behavior rather than
replace it, `Programmer.Put` calls `Person.Put` as part of its behavior.
It does this by converting its parameter from the type
`Programmer.Object` to its ancestor type `Person.Object`. This construct
is a *view conversion*; contrary to a normal type conversion, it does
*not* create a new object and does *not* incur any run-time cost (and
indeed, if the operand of such *view conversion* was actually a
variable, the result can be used when an out parameter is required (eg.
procedure call)). Of course, it is optional that an overriding operation
call its ancestor; there are cases where the intent is indeed to
replace, not extend, the inherited behavior.

(Note that also for untagged types, overriding of inherited operations
is possible. The reason why it\'s discussed here is that derivation of
untagged types is done rather seldom.)

### Polymorphism, class-wide programming and dynamic dispatching

The full power of object orientation is realized by polymorphism,
class-wide programming and dynamic dispatching, which are different
words for the same, single concept. To explain this concept, let us
extend the example from the previous sections, where we declared a base
tagged type `Person.Object` with a primitive operation `Put` and a
record extension `Programmer.Object` with additional data and an
overriding primitive operation `Put`.

Now, let us imagine a collection of persons. In the collection, some of
the persons are programmers. We want to traverse the collection and call
`Put` on each person. When the person under consideration is a
programmer, we want to call `Programmer.Put`; when the person is not a
programmer, we want to call `Person.Put`. This, in essence, is
polymorphism, class-wide programming and dynamic dispatching.

With Ada\'s strong typing, ordinary calls cannot be dynamically
dispatched; a call to an operation on a declared type must always be
statically bound to go to the operation defined for that specific type.
Dynamic dispatching (known as simply *dispatching* in Ada parlance) is
provided through separate *class-wide types* that are polymorphic. Each
tagged type, such as `Person.Object`, has a corresponding *class of
types* which is the set of types comprising the type `Person.Object`
itself and all types that extend `Person.Object`. In our example, this
class consists of two types:

-   `Person.Object`
-   `Programmer.Object`

Ada 95 defines the `Person.Object'Class` attribute to denote the
corresponding class-wide type. In other words:

\
`   Someone : Person.Object'Class := ...; `\
\
`   Someone.Put; `\
`;`

The declaration of Someone denotes an object that may be of *either*
type, `Person.Object` or `Programmer.Object`. Consequently, the call to
the primitive operation `Put` dispatches dynamically to either
`Person.Put` or `Programmer.Put`.

The only problem is that, since we don\'t know whether Someone is a
programmer or not, we don\'t know how many data components Someone has,
either, and therefore we don\'t know how many bytes Someone takes in
memory. For this reason, the class-wide type `Person.Object'Class` is
*indefinite*.
It is impossible to declare an object of this type without giving some
constraint. It is, however, possible to:

-   declare an object of a class-wide with an initial value (as above).
    The object is then constrained by its initial value.
-   declare an *access value* to such an object (because the access
    value has a known size);
-   pass objects of a class-wide type as parameters to subprograms
-   assign an object of a specific type (in particular, the result of a
    function call) to a variable of a class-wide type.

With this knowledge, we can now build a polymorphic collection of
persons; in this example we will quite simply create an array of access
values to persons:

` Person;`\
` Main `\
`   `` Person_Access `` Person.Object'Class;`\
`   `` Array_Of_Persons  `` (Positive `` <>) of Person_Access;`\
\
`   `` Read_From_Disk `` Array_Of_Persons ``;`\
\
`   Everyone : `` Array_Of_Persons := Read_From_Disk;`\
` `\
`   `` K `` Everyone'Range `\
`      Everyone (K).``.Put; `\
`   ``;`\
` Main;`

The above procedure achieves our desired goal: it traverses the array of
Persons and calls the procedure `Put` that is appropriate for each
person.

#### Advanced topic: How dynamic dispatching works

You don\'t need to know how dynamic dispatching works in order to use it
effectively but, in case you are curious, here is an explanation.

The first component of each object in memory is the *tag*; this is why
objects are of a *tagged* type rather than plain records. The tag really
is an access value to a table; there is one table for each specific
type. The table contains access values to each primitive operation of
the type. In our example, since there are two types `Person.Object` and
`Programmer.Object`, there are two tables, each containing a single
access value. The table for `Person.Object` contains an access value to
`Person.Put` and the table for `Programmer.Object` contains an access
value to `Programmer.Put`. When you compile your program, the compiler
constructs both tables and places them in the program executable code.

Each time the program creates a new object of a specific type, it
automatically sets its tag to point to the appropriate table.

Each time the program performs a *dispatching call* of a primitive
operation, the compiler inserts object code that:

-   dereferences the tag to find the table of primitive operations for
    the specific type of the object at hand
-   dereferences the access value to the primitive operation
-   calls the primitive operation.

Conversely, when the program performs a call where the parameter is a
view conversion to an ancestor type, the compiler performs these two
dereferences at compile time rather than run time: such a call is
*statically bound*; the compiler emits code that directly calls the
primitive operation of the ancestor type specified in the view
conversion.

#### Redispatching

Dispatching is controlled by the (hidden) tag of the object. So what
happens when a primitive operation `Op1` calls another primitive
operation `Op2` on the same object?

` `` Root `` `` ``;`\
` `` Op1 (This: Root);`\
` `` Op2 (This: Root);`\
\
` `` Derived `` `` Root `` ``;`\
` -- Derived inherits Op1`\
` `` `` Op2 (This: Derived);`\
\
` `` Op1 (This: Root) `\
` `\
`   ...`\
`   Op2 (This);               -- not redispatching`\
`   Op2 (Root'Class (This));  -- redispatching`\
`   This.Op2;                 -- not redispatching (new syntax since Ada 2005)`\
`   (Root'Class (This)).Op2;  -- redispatching (new syntax since Ada 2005)`\
`   ...`\
` `` Op1;`\
\
` D: Derived;`\
` C: Root'Class := D;`\
\
` Op1 (D);  -- statically bound call`\
` Op1 (C);  -- dispatching call`\
` D.Op1;    -- statically bound call (new syntax since Ada 2005)`\
` C.Op1;    -- dispatching call (new syntax since Ada 2005)`

In this fragment, `Op1` is not overridden, whereas `Op2` is overridden.
The body of `Op1` calls `Op2`, so which `Op2` will be called if `Op1` is
called for an object of type `Derived`?

The basic rules of dispatching still apply. Calls to `Op2` will be
dispatched when called using an object of a class-wide type.

The formal parameter lists for the operations specify the type of `This`
to be a specific type, not class-wide. In fact, that parameter *must* be
a specific type so that the operation will be dispatched for objects of
that type, and to allow the operation\'s code to access any additional
data items associated with that type. If you want redispatching, you
must state that explicitly by converting the parameter of the specific
type to the class-wide type again. (Remember: view conversions never
lose components, they just hide them. A conversion to a class-wide type
can unhide them again.) The first call `Op1 (D)` (statically bound,
i.e., not dispatching) executes the inherited `Op1` --- and within
`Op1`, the first call to `Op2` is also statically bound (there is no
redispatching) because parameter `This` is a view conversion to specific
type `Root`. However, the second call is dispatching because the
parameter `This` is converted to the class-wide type. That call
dispatches to the overriding `Op2`.

Because the conventional `This.Op2` call is *not* dispatching, the call
will be to `Root.Op2` even though the object itself is of type `Derived`
and the `Op2` operation is overridden. *This is very different from how
other OO languages behave.* In other OO languages, a method is either
dispatching or not. In Ada, an operation is either *available* for
dispatching or not. Whether or not dispatching is actually *used* for a
given call depends on the way that the object\'s type is specified at
that call point. For programmers accustomed to other OO languages, it
can come as quite a surprise that calls from a dispatchable operation to
other operations on the same object are, by default, *not* (dynamically)
dispatched.

The default of not redispatching is not an issue if all of the
operations have been overridden, because they all will be operating on
the expected type of object. However, it has ramifications when writing
code for types that might be extended by another type sometime in the
future. It\'s possible that the new type will not work as intended if it
doesn\'t override all of the primitive operations that call other
primitive operations. The safest policy is to use a class-wide
conversion of the object to force dispatching of calls. One way to
accomplish that is to define a class-wide constant in each dispatched
method:

` `` Op2 (This: Derived) `\
`   This_Class: `` Root'Class := This;`\
` `

`This` is needed to access data items and to make any non-dispatching
calls. `This_Class` is needed to make dispatching calls.

Less commonly encountered and perhaps less surprising, calls from a
non-dispatchable (class-wide) routine for a tagged type to other
routines on the same object are, by default, dispatched:

` `` Root `` `` ``;`\
` `` Op1 (This: Root'Class);`\
` `` Op2 (This: Root);`\
\
` `` Derived `` `` Root `` ``;`\
` -- Derived does `**`not`**` inherit Op1, rather Op1 is applicable to Derived.`\
` `` `` Op2 (This: Derived);`\
\
` `` Op1 (This: Root'Class) `\
` `\
`   ...`\
`   Op2 (This);               -- dispatching`\
`   Op2 (Root (This));        -- static call`\
`   This.Op2;                 -- dispatching (new syntax since Ada 2005)`\
`   (Root (This)).Op2;        -- static call (new syntax since Ada 2005)`\
`   ...`\
` `` Op1;`\
\
` D: Derived;`\
` C: Root'Class := D;`\
\
` Op1 (D);  -- static call`\
` Op1 (C);  -- static call`\
` D.Op1;    -- static call (new syntax since Ada 2005)`\
` C.Op1;    -- static call (new syntax since Ada 2005)`

Note that calls on `Op1` are always static, since `Op1` is *not*
inherited. Its parameter type is class-wide, so the operation is
*applicable* to all types derived from Root. (Op2 has an entry for each
type derived from `Root` in the dispatch table. There is no such
dispatch table for `Op1`; rather there is only one such operation for
all types in the class.)

Normal calls *from* `Op1` are dispatched because the declared type of
`This` is class-wide. The default to dispatching usually isn\'t
bothersome because class-wide operations are typically used to perform a
script involving calls to one or more dispatched operations.

#### Run-time type identification

Run-time type identification allows the program to (indirectly or
directly) query the tag of an object at run time to determine which type
the object belongs to. This feature, obviously, makes sense only in the
context of polymorphism and dynamic dispatching, so works only on tagged
types.

You can determine whether an object belongs to a certain class of types,
or to a specific type, by means of the membership test
, like this:

` Base    `` `` ``;`\
` Derived `` `` Base    `` ``;`\
` Leaf    `` `` Derived `` ``;`\
\
`...`\
` Explicit_Dispatch (This : `` Base'Class) `\
\
`   `` This `` Leaf `` ... ``;`\
`   `` This `` Derived'Class `` ... ``;`\
` Explicit_Dispatch;`

Thanks to the strong typing rules of Ada, run-time type identification
is in fact rarely needed; the distinction between class-wide and
specific types usually allows the programmer to ensure objects are of
the appropriate type without resorting to this feature.

Additionally, the reference manual defines `package Ada.Tags` (RM
3.9(6/2)), attribute `'Tag` (RM 3.9(16,18)), and
`function Ada.Tags.Generic_Dispatching_Constructor` (RM 3.9(18.2/2)),
which enable direct manipulation with tags.

### Creating Objects

The Language Reference Manual\'s section on
 states when
an object is created, and destroyed again. This subsection illustrates
how objects are created.

The LRM section starts,

For example, assume a typical hierarchy of object oriented types: a
top-level type `Person`, a `Programmer` type derived from `Person`, and
possibly more kinds of persons. Each person has a name; assume `Person`
objects to have a `Name` component. Likewise, each `Person` has a
`Gender` component. The `Programmer` type inherits the components and
the operations of the `Person` type, so `Programmer` objects have a
`Name` and a `Gender` component, too. `Programmer` objects may have
additional components specific to programmers.

Objects of a tagged type are created the same way as objects of any
type. The second LRM sentence says, for example, that an object will be
created when you declare a variable or a constant of a type. For the
tagged type `Person`,

\
`   P`` Person`\
\
`   Text_IO``Put_Line``"The name is " `` P``Name`\

Nothing special so far. Just like any ordinary variable declaration this
O-O one is elaborated. The result of elaboration is an object named `P`
of type `Person`. However, `P` has only default name and gender value
components. These are likely not useful ones. One way of giving initial
values to the object\'s components is to assign an aggregate.

\
`   P`` Person `` ``Name `` "Scorsese"`` Gender `` Male`\
\
`   Text_IO``Put_Line``"The name is " `` P``Name`\

The parenthesized expression after := is called an *aggregate*
().

Another way to create an object that is mentioned in the LRM paragraph
is to call a function. An object will be created as the return value of
a function call. Therefore, instead of using an aggregate of initial
values, we might call a function returning an object.

Introducing proper O-O information hiding, we change the package
containing the `Person` type so that `Person` becomes a private type. To
enable clients of the package to construct `Person` objects we declare a
function that returns them. (The function may do some interesting
construction work on the objects. For instance, the aggregate above will
most probably raise the exception Constraint_Error depending on the name
string supplied; the function can mangle the name so that it matches the
declaration of the component.) We also declare a function that returns
the name of `Person` objects.

` Persons `\
\
`   `` Person `` `` `\
\
`   `` Make ``Name`` String`` Sex`` Gender_Type`` `` Person`\
\
`   `` Name ``P`` Person`` `` String`\
\
\
`   `` Person `` `\
`      `\
`         Name   `` String ``1 `` 10`\
`         Gender `` Gender_Type`\
`      `` `\
\
` Persons`

Calling the `Make` function results in an object which can be used for
initialization. Since the `Person` type is **private** we can no longer
refer to the `Name` component of `P`. But there is a corresponding
function `Name` declared with type `Person` making it a socalled
primitive operation. (The component and the function in this example are
both named `Name` However, we can choose a different name for either if
we want.)

\
`   P`` Person `` Make ``Name `` "Orwell"`` Sex `` Male`\
\
`   Text_IO``Put_Line``"The name is " `` Name``P`\

Objects can be copied into another. The target object is first
destroyed. Then the component values of the source object are assigned
to the corresponding components of the target object. In the following
example, the default initialized `P` gets a copy of one of the objects
created by the `Make` calls.

\
`   P`` Person`\
\
`   `` 2001 `` 1984 `\
`      P `` Make ``Name `` "Kubrick"`` Sex `` Male`\
`   `\
`      P `` Make ``Name `` "Orwell"`` Sex `` Male`\
`   `` `\
\
`   Text_IO``Put_Line``"The name is " `` Name``P`\

So far, there is no mention of the `Programmer` type derived from
`Person`. There is no polymorphism yet, and likewise initialization does
not yet mention inheritance. Before dealing with `Programmer` objects
and their initialization a few words about class-wide types are in
order.

### More details on primitive operations

Remember what we said before about \"Primitive
Operations\". Primitive operations
are:

-   subprograms taking a parameter of the tagged type;
-   functions returning an object of the tagged type;
-   subprograms taking a parameter of an *anonymous access type* to the
    tagged type;
-   In Ada 2005 only, functions returning an *anonymous access type* to
    the tagged type;

Additionally, primitive operations must be declared before the type is
*frozen* (the concept of freezing will be explained later):

Examples:

` X `\
`   `` Object `` `` `` ``;`\
\
`   `` Primitive_1 (This : ``     Object);`\
`   `` Primitive_2 (That :    `` Object);`\
`   `` Primitive_3 (Me   : `` `` Object);`\
`   `` Primitive_4 (Them : `` Object);`\
`   ``  Primitive_5 `` Object;`\
`   ``  Primitive_6 (Everyone : Boolean) `` `` Object;`\
` X;`

All of these subprograms are primitive operations.

A primitive operation can also take parameters of the same or other
types; also, the controlling operand does not have to be the first
parameter:

` X `\
`   `` Object `` `` `` ``;`\
\
`   `` Primitive_1 (This : `` Object; Number : `` Integer);`\
`   `` Primitive_2 (You  : `` Boolean; That : `` Object);`\
`   `` Primitive_3 (Me, Her : `` `` Object);`\
` X;`

The definition of primitive operations specifically excludes named
access types and class-wide types as well as operations not defined
immediately in the same declarative region. Counter-examples:

` X `\
`   `` Object `` `` `` ``;`\
`   `` Object_Access `` `` Object;`\
`   `` Object_Class_Access `` `` Object'Class;`\
\
`   `` Not_Primitive_1 (This : ``     Object'Class);`\
`   `` Not_Primitive_2 (This : `` `` Object_Access);`\
`   `` Not_Primitive_3 (This :    `` Object_Class_Access);`\
`   ``  Not_Primitive_4 `` Object'Class;`\
\
`   `` Inner `\
`       `` Not_Primitive_5 (This : `` Object);`\
`   `` Inner;`\
` X;`

#### Advanced topic: Freezing rules

Freezing rules (ARM
13.14) are
perhaps the most complex part of the Ada language definition; this is
because the standard tries to describe freezing as unambiguously as
possible. Also, that part of the language definition deals with freezing
of all entities, including complicated situations like generics and
objects reached by dereferencing access values. You can, however, get an
intuitive understanding of freezing of tagged types if you understand
how dynamic dispatching
works. In
that section, we saw that the compiler emits a table of primitive
operations for each tagged type. The point in the program text where
this happens is the point where the tagged type is *frozen*, i.e. the
point where the table becomes complete. After the type is frozen, no
more primitive operations can be added to it.

This point is the earliest of:

-   the end of the package spec where the tagged type is declared
-   the appearance of the first type derived from the tagged type

Example:

` X `\
\
`  `` Object `` `` `` ``;`\
`  `` Primitive_1 (This: `` Object);`\
\
`  -- this declaration freezes Object`\
`  `` Derived `` `` Object `` `` ``;`\
\
`  -- illegal: declared after Object is frozen`\
`  `` Primitive_2 (This: `` Object);`\
\
` X;`

Intuitively: at the point where Derived is declared, the compiler starts
a new table of primitive operations for the derived type. This new
table, initially, is equal to the table of the primitive operations of
the parent type, `Object`. Hence, `Object` must freeze.

-   the declaration of a variable of the tagged type

Example:

` X `\
\
`  `` Object `` `` `` ``;`\
`  `` Primitive_1 (This: `` Object);`\
\
`  V: Object;  -- this declaration freezes Object`\
\
`  -- illegal: Primitive operation declared after Object is frozen`\
`  `` Primitive_2 (This: `` Object);`\
\
` X;`

Intuitively: after the declaration of `V`, it is possible to call any of
the primitive operations of the type on `V`. Therefore, the list of
primitive operations must be known and complete, i.e. frozen.

-   The completion (*not* the declaration, if any) of a constant of the
    tagged type:

` X `\
\
`  `` Object `` `` `` ``;`\
`  `` Primitive_1 (This: `` Object);`\
\
`  -- this declaration does NOT freeze Object`\
`  Deferred_Constant: `` Object;`\
\
`  `` Primitive_2 (This : `` Object); -- OK`\
\
\
\
`  -- only the completion freezes Object`\
`  Deferred_Constant: `` Object := (`` ``);`\
\
`  -- illegal: declared after Object is frozen`\
`  `` Primitive_3 (This: `` Object);`\
\
` `` X;`

### New features of Ada 2005

Ada 2005 adds overriding indicators, allows anonymous access types in
more places and offers the object.method notation.

#### Overriding indicators

The new keyword  can be used to
indicate whether an operation overrides an inherited subprogram or not.
Its use is optional because of upward-compatibility with Ada 95. For
example:

` X `\
`    `` Object `` `` `` ``;`\
\
`   ``  Primitive `` `` Object; `\
\
`   `` Derived_Object `` `` Object `` `` ``;`\
\
`   `` `\
`   `` Primitive (This : `` Derived_Object); `\
\
`   `\
`   ``  Primitive `` Derived_Object;`\
` X;`

The compiler will check the desired behaviour.

This is a good programming practice because it avoids some nasty bugs
like not overriding an inherited subprogram because the programmer spelt
the identifier incorrectly, or because a new parameter is added later in
the parent type.

It can also be used with abstract operations, with renamings, or when
instantiating a generic subprogram:

` `\
` Primitive_X (This : `` Object) `` ``;`\
\
\
`  Primitive_Y `` Object `` Some_Other_Subprogram;`\
\
` `\
` Primitive_Z (This : `` Object)`\
`      `` `` Generic_Procedure (Element => Integer);`

#### Object.Method notation

We have already seen this notation:

` X `\
`   `` Object `` `` `` ``;`\
\
`   `` Primitive (This: `` Object; That: `` Boolean);`\
` X;`

` X;`\
` Main `\
`   Obj : X.Object;`\
\
`   Obj.Primitive (That => True); `\
` Main;`

This notation is only available for primitive operations where the
controlling parameter is the *first* parameter.

### Abstract types

A tagged type can also be abstract (and thus can have abstract
operations):

` X `\
\
`   `` Object `` `` `` …;`\
\
`   `` One_Class_Member      (This : ``     Object);`\
`   `` Another_Class_Member  (This : `` `` Object);`\
`   ``  Abstract_Class_Member `` Object  `` ``;`\
\
` X;`

An abstract operation cannot have any body, so derived types are forced
to override it (unless those derived types are also abstract). See next
section about interfaces for more information about this.

The difference with a non-abstract tagged type is that you cannot
declare any variable of this type. However, you can declare an access to
it, and use it as a parameter of a class-wide operation.

### Multiple Inheritance via Interfaces

Interfaces allow for a limited form of multiple inheritance (taken from
Java). On a semantic level they are similar to an \"abstract tagged null
record\" as they may have primitive operations but cannot hold any data
and thus these operations cannot have a body, they are either declared
 or .
*Abstract* means the operation has to be overridden, *null* means the
default implementation is a null body, i.e. one that does nothing.

An interface is declared with:

` Printable `\
`   `` Object `` ``;`\
`   `` Class_Member_1 (This : ``     Object) `` ``;`\
`   `` Class_Member_2 (This :    `` Object) `` ``;`\
` Printable;`

You implement an  by adding it to a
concrete *class*:

` Person;`\
` Programmer `\
`   `` Object `` `` Person.Object`\
`                  `` Printable.Object`\
`   `\
`      `\
`         Skilled_In : Language_List;`\
`      `` ``;`\
`   `\
`   `` Class_Member_1   (This : `` Object);`\
`   `` `\
`   `` New_Class_Member (This : Object; That : String);`\
` Programmer;`

As usual, all inherited abstract operations must be overridden although
*null subprograms* ones need not.

Such a type may implement a list of interfaces (called the
*progenitors*), but can have only one *parent*. The parent may be a
concrete type or also an interface.

` Derived `` `` Parent `` Progenitor_1 `` Progenitor_2 ... `` ...;`

### Multiple Inheritance via Mix-in

Ada supports multiple inheritance of *interfaces* (see above), but only
single inheritance of *implementation*. This means that a tagged type
can *implement* multiple interfaces but can only *extend* a single
ancestor tagged type.

This can be problematic if you want to add behavior to a type that
already extends another type; for example, suppose you have

` Base ``;`\
` Derived `` Base ``;`

and you want to make `Derived` controlled, i.e. add the behavior that
`Derived` controls its initialization, assignment and finalization. Alas
you cannot write:

` Derived `` Base `` ``.Controlled ``; `

since  for historical
reasons does not define interfaces `Controlled` and
`Limited_Controlled`, but abstract types.

If your base type is not limited, there is no good solution for this;
you have to go back to the root of the class and make it controlled.
(The reason will become obvious presently.)

For limited types however, another solutions is the use of a mix-in:

` Base ``;`\
` Derived;`\
\
` Controlled_Mix_In (Enclosing: `` Derived) `\
`  `` ``.Limited_Controlled ``;`\
\
` Initialize (This: `` Controlled_Mix_In);`\
` Finalize   (This: `` Controlled_Mix_In);`\
\
` Derived `` Base `\
`  Mix_In: Controlled_Mix_In (Enclosing => Derived'Access); `\
`  `\
`;`

This special kind of mix-in is an object with an access discriminant
that references its enclosing object (also known as *Rosen trick*). In
the declaration of the `Derived` type, we initialize this discriminant
with a special syntax: `Derived'Access` really refers to an access value
to the *current instance* of type `Derived`. Thus the access
discriminant allows the mix-in to see its enclosing object and all its
components; therefore it can initialize and finalize its enclosing
object:

` Initialize (This: `` Controlled_Mix_In) `\
`  Enclosing: Derived `` This.Enclosing.``;`\
\
`  `\
` Initialize;`

and similarly for `Finalize`.

The reason why this does not work for non-limited types is the
self-referentiality via the discriminant. Imagine you have two variables
of such a non-limited type and assign one to the other:

`X := Y;`

In an assignment statement, `Adjust` is called only *after* `Finalize`
of the target `X` and so cannot provide the new value of the
discriminant. Thus `X.Mixin_In.Enclosing` will inevitably reference `Y`.

Now let\'s further extend our hierarchy:

` Further `` Derived ``;`\
\
` Initialize (This: `` Further);`\
` Finalize   (This: `` Further);`

Oops, this does not work because there are no corresponding procedures
for `Derived`, yet -- so let\'s quickly add them.

` Base ``;`\
` Derived;`\
\
` Controlled_Mix_In (Enclosing: `` Derived) `\
`  `` ``.Limited_Controlled ``;`\
\
` Initialize (This: `` Controlled_Mix_In);`\
` Finalize   (This: `` Controlled_Mix_In);`\
\
` Derived `` Base `\
`  Mix_In: Controlled_Mix_In (Enclosing => Derived'Access);  `\
`  `\
`;`\
\
` Initialize (This: `` Derived);  `\
` Finalize   (This: `` Derived);`\
\
` Further `` Derived ``;`

` Initialize (This: `` Further);`\
` Finalize   (This: `` Further);`

We have of course to write `not overriding` for the procedures on
`Derived` because there is indeed nothing they could override. The
bodies are

` Initialize (This: `` Derived) `\
\
`  `\
` Initialize;`

` Initialize (This: `` Controlled_Mix_In) `\
`  Enclosing: Derived `` This.Enclosing.``;`\
\
`  Initialize (Enclosing);`\
` Initialize;`

To our dismay, we have to learn that `Initialize/Finalize` for objects
of type `Further` will not be called, instead those for the parent
`Derived`. Why?

\
`  X: Further;  -- Initialize (Derived (X)) is called here`\
\
`  ``;`\
`;  -- Finalize (Derived (X)) is called here`

The reason is that the mix-in defines the local object `Enclosing` to be
of type `Derived` in the renames-statement above. To cure this, we have
necessarily to use the dreaded redispatch (shown in different but
equivalent notations):

` Initialize (This: `` Controlled_Mix_In) `\
`  Enclosing: Derived `` This.Enclosing.``;`\
\
`  Initialize (Derived'Class (Enclosing));`\
` Initialize;`

` Finalize (This: `` Controlled_Mix_In) `\
`  Enclosing: Derived'Class `` Derived'Class (This.Enclosing.``);`\
\
`  Enclosing.Finalize;`\
` Finalize;`

\
`  X: Further;  -- Initialize (X) is called here`\
\
`  ``;`\
`;  -- Finalize (X) is called here`

Alternatively (and presumably better still) is to write

` Controlled_Mix_In (Enclosing: `` Derived'Class) `\
`  `` ``.Limited_Controlled ``;`

Then we automatically get redispatch and can omit the type conversions
on `Enclosing`.

## Class names

Both the class package and the class record need a name. In theory they
may have the same name, but in practice this leads to nasty
`<small>`{=html}(because of unintuitive error messages)`</small>`{=html}
name clashes when you use the  clause. So
over time three de facto naming standards have been commonly used.

### Classes/Class

The package is named by a plural noun and the record is named by the
corresponding singular form.

` Persons `\
\
`   `` Person `` `\
`      `\
`         Name   : String (1 .. 10);`\
`         Gender : Gender_Type;`\
`      `` ``;`\
\
` Persons;`

This convention is the usually used in Ada\'s built-in libraries.

Disadvantage: Some \"multiples\" are tricky to spell, especially for
those of us who aren\'t native English speakers.

### Class/Object

The package is named after the class, the record is just named Object.

` Person `\
\
`   `` Object `` `\
`      `\
`         Name   : String (1 .. 10);`\
`         Gender : Gender_Type;`\
`      `` ``;`\
\
` Person;`

Most UML and
IDL code generators use
this technique.

Disadvantage: You can\'t use the  clause on
more than one such class packages at any one time. However you can
always use the \"type\" instead of the package.

### Class/Class_Type

The package is named after the class, the record is postfixed with
*\_Type*.

` Person `\
\
`   `` Person_Type `` `\
`      `\
`         Name   : String (1 .. 10);`\
`         Gender : Gender_Type;`\
`      `` ``;`\
\
` Person;`

Disadvantage: lots of ugly \"\_Type\" postfixes.

## Object-Oriented Ada for C++ programmers

In C++, the construct

``` c++
 struct C {
   virtual void v();
   void w();
   static void u();
 };
```

is strictly equivalent to the following in Ada:

` P `\
`  `` C ``;`\
`  `` V (This : `` C);        `\
`  `` W (This : `` C'Class);  `\
`  `` U;`\
` P;`

In C++, member functions implicitly take a parameter `this` which is of
type `C*`. In Ada, all parameters are explicit. As a consequence, the
fact that `u()` does *not* take a parameter is implicit in C++ but
explicit in Ada.

In C++, `this` is a pointer. In Ada, the explicit `This` parameter does
not have to be a pointer; all parameters of a tagged type are implicitly
passed by reference anyway.

### Static dispatching

In C++, function calls dispatch statically in the following cases:

-   the target of the call is an object type
-   the member function is non-virtual

For example:

``` c++
 C object;
 object.v();
 object.w();
```

both dispatch statically. In particular, the static dispatch for v() may
be confusing; this is because object is neither a pointer nor a
reference. Ada behaves exactly the same in this respect, except that Ada
calls this *static binding* rather than *dispatching*:

\
`   Object : P.C;`\
\
`   Object.V; `\
`   Object.W; `\
`;`

### Dynamic dispatching

In C++, a function call dispatches dynamically if the two following
conditions are met simultaneously:

-   the target of the call is a pointer or a reference
-   the member function is virtual.

For example:

``` c++
 C* object;
 object->v(); // dynamic dispatch
 object->w(); // static, non-virtual member function
 object->u(); // illegal: static member function
 C::u(); // static dispatch
```

In Ada, a primitive subprogram call dispatches (dynamically) if and only
if:

-   the target object is of a class-wide type;

Note: In Ada vernacular, the term *dispatching* always means *dynamic*.

For example:

\
`   Object : P.C'Class := ...;`\
\
`   P.V (Object); `\
`   P.W (Object); `\
`   P.U; `\
`;`

As can be seen *there is no need for access types or pointers* to do
dispatching in Ada. In Ada, *tagged types are always passed by-reference
to subprograms* without the need for explicit access values.

Also note that in C++, the class serves as:

-   the unit of encapsulation (Ada uses packages and visibility for
    this)
-   the type, like in Ada.

As a consequence, you call C::u() in C++ because u() is encapsulated in
C, but P.U in Ada since U is encapsulated in the *package* P, not the
*type* C.

### Class-wide and specific types

The most confusing part for C++ programmers is the concept of a
\"class-wide type\". To help you understand:

-   pointers and references in C++ are really, implicitly, class-wide;
-   object types in C++ are really specific;
-   C++ provides no way to declare the equivalent of:

` C_Specific_Access `` C;`

-   C++ provides no way to declare the equivalent of:

` C_Specific_Access_One `` C;`\
` C_Specific_Access_Two `` C;`

which, in Ada, are two different, *incompatible* types, possibly
allocating their memory from different storage pools!

-   In Ada, you do *not* need access values for dynamic dispatching.
-   In Ada, you use access values for dynamic memory management (only)
    and class-wide types for dynamic dispatching (only).
-   In C++, you use pointers and references both for dynamic memory
    management and for dynamic dispatching.
-   In Ada, class-wide types are explicit (with `'Class`).
-   In C++, class-wide types are implicit (with `*` or `&`).

### Constructors

in C++, a special syntax declares a constructor:

``` c++
 class C {
    C(/* optional parameters */); // constructor
 };
```

A constructor cannot be virtual. A class can have as many constructors,
differentiated by their parameters, as necessary.

Ada does not have such constructors. Perhaps they were not deemed
necessary since in Ada, any function that returns an object of the
tagged type can serve as a kind of constructor. This is however not the
same as a real constructor like the C++ one; this difference is most
striking in cases of derivation trees (see Finalization below). The Ada
constructor subprograms do not have to have a special name and there can
be as many constructors as necessary; each function can take parameters
as appropriate.

` P `\
`  `` T is `` ``;`\
`  `` Make                 `` T;  -- constructor`\
`  `` To_T (From: Integer) `` T;  -- another constructor`\
`  `` Make (This: `` T);            -- not a constructor`\
\
`  ...`\
` P;`

If an Ada constructor function is also a primitive operation (as in the
example above), it becomes abstract upon derivation and has to be
overridden if the derived type is not itself abstract. If you do not
want this, declare such functions in a nested scope.

In C++, one idiom is the *copy constructor* and its cousin the
*assignment operator*:

``` c++
 class C {
    C(const C& that); // copies "that" into "this"
    C& operator= (const C& right); // assigns "right" to "this", which is "left"
 };
```

This copy constructor is invoked implicitly on initialization, e.g.

``` c++
 C a = b; // calls the copy constructor
 C c;
 a = c;   // calls the assignment operator
```

Ada provides a similar functionality by means of *controlled types*. A
controlled type is one that extends the predefined type
`.Controlled`:

` ``;`\
` P `\
`  `` T `` `` ``.Controlled `` ``;`\
`  `` Make `` T;  -- constructor`\
\
`  `` T `` ... `` ``;`\
`  `` `` Initialize (This: `` `` T);`\
`  `` `` Adjust     (This: `` `` T); -- copy constructor`\
` P;`

Note that Initialize is not a constructor; it resembles the C++
constructor in some way, but is also very different. Suppose you have a
type T1 derived from T with an appropriate overriding of Initialize. A
real constructor (like the C++ one) would automatically first construct
the parent components (T), then the child components. In Ada, this is
not automatic. In order to mimic this in Ada, we have to write:

` Initialize (This: `` `` T1) `\
\
`  Initialize (T (This));  -- Don't forget this part!`\
`  ...  -- handle the new components here`\
` Initialize;`

The compiler inserts a call to Initialize after each object of type T is
allocated when no initial value is given. It also inserts a call to
Adjust after each assignment to the object. Thus, the declarations:

`A: T;`\
`B: T := X;`

will:

-   allocate memory for A
-   call Initialize (A)
-   allocate memory for B
-   copy the contents of X to B
-   call Adjust (B)

Initialize (B) will not be called because of the explicit
initialization.

So, the equivalent of a copy constructor is an overriding of Adjust.

If you would like to provide this functionality to a type that extends
another, non-controlled type, see \"Multiple
Inheritance\".

### Destructors

In C++, a destructor is a member function with only the implicit `this`
parameter:

``` c++
 class C {
    virtual ~C(); // destructor
 }
```

While a constructor *cannot* be virtual, a destructor *must* be virtual
if the class is to be used with dynamic dispatch (has virtual methods or
derives from a class with virtual methods). C++ classes do not use
dynamic dispatch by default, so it can catch some programmers out and
wreak havoc in their programs by simply forgetting the keyword
`virtual`.

In Ada, the equivalent functionality is again provided by controlled
types, by overriding the procedure Finalize:

` ``;`\
` P `\
`   `` T `` `` ``.Controlled `` ``;`\
`   `` Make `` T;  -- constructor`\
\
`   `` T `` ... `` ``;`\
`   `` `` Finalize (This: `` `` T);  -- destructor`\
` P;`

Because Finalize is a primitive operation, it is automatically
\"virtual\"; you cannot, in Ada, forget to make a destructor virtual.

### Encapsulation: public, private and protected members

In C++, the unit of encapsulation is the class; in Ada, the unit of
encapsulation is the package. This has consequences on how an Ada
programmer places the various components of an object type.

``` c++
 class C {
 public:
    int a;
    void public_proc();
 protected:
    int b;
    int protected_func();
 private:
    bool c;
    void private_proc();
 };
```

A way to mimic this C++ class in Ada is to define a hierarchy of types,
where the base type is the public part, which must be abstract so that
no stand-alone objects of this base type can be defined. It looks like
so:

` `` ``;`\
\
` CPP `\
\
`  `` Public_Part `` `` `` ``  -- no objects of this type`\
`    A: Integer;`\
`  `` ``;`\
\
`  `` Public_Proc (This: `` `` Public_Part);`\
\
`  `` Complete_Type `` `` Public_Part `` ``;`\
\
`  -- procedure Public_Proc (This: in out Complete_Type);  -- inherited, implicitly defined`\
\
`  -- visible for children`\
\
`  `` Private_Part;  -- declaration stub`\
`  `` Private_Part_Pointer `` `` Private_Part;`\
\
`  `` Private_Component `` `` ``.Controlled `` `\
`    P: Private_Part_Pointer;`\
`  `` record;`\
\
`  `` `` Initialize (X: `` `` Private_Component);`\
`  `` `` Adjust     (X: `` `` Private_Component);`\
`  `` `` Finalize   (X: `` `` Private_Component);`\
\
`  `` Complete_Type `` `` Public_Part `` `\
`    B: Integer;`\
`    P: Private_Component;  -- must be controlled to avoid storage leaks`\
`  `` ``;`\
\
`  `` `` `` Protected_Proc (This: Complete_Type);`\
\
` CPP;`

The private part is defined as a stub only, its completion is hidden in
the body. In order to make it a component of the complete type, we have
to use a pointer since the size of the component is still unknown (the
size of a pointer is known to the compiler). With pointers,
unfortunately, we incur the danger of memory leaks, so we have to make
the private component controlled.

For a little test, this is the body, where the subprogram bodies are
provided with identifying prints:

` Ada.Unchecked_Deallocation;`\
` Ada.Text_IO;`\
\
` `` CPP `\
\
`  `` Public_Proc (This: `` `` Public_Part) ``  -- primitive`\
`  `\
`    Ada.Text_IO.Put_Line ("Public_Proc" & Integer'Image (This.A));`\
`  `` Public_Proc;`\
\
`  `` Private_Part `` ``  -- complete declaration`\
`    C: Boolean;`\
`  `` ``;`\
\
`  `` `` Initialize (X: `` `` Private_Component) `\
`  `\
`    X.P := new Private_Part'(C => True);`\
`    Ada.Text_IO.Put_Line ("Initialize " & Boolean'Image (X.P.C));`\
`  `` Initialize;`\
\
`  `` `` (X: `` `` Private_Component) `\
`  `\
`    Ada.Text_IO.Put_Line ("Adjust " & Boolean'Image (X.P.C));`\
`    X.P := new Private_Part'(C => X.P.C);  -- deep copy`\
`  `` Adjust;`\
\
`  `` `` Finalize (X: `` `` Private_Component) `\
`    `` Free `` `` Ada.Unchecked_Deallocation (Private_Part, Private_Part_Pointer);`\
`  `\
`    Ada.Text_IO.Put_Line ("Finalize " & Boolean'Image (X.P.C));`\
`    Free (X.P);`\
`  `` Finalize;`\
\
`  `` Private_Proc (This: `` `` Complete_Type) ``  -- not primitive`\
`  `\
`    Ada.Text_IO.Put_Line ("Private_Proc" & Integer'Image (This.A) & Integer'Image (This.B) & ' ' & Boolean'Image (This.P.P.C));`\
`  `` Private_Proc;`\
\
`  `` `` `` Protected_Proc (This: Complete_Type) ``  -- primitive`\
`    X: Complete_Type := This;`\
`  `\
`    Ada.Text_IO.Put_Line ("Protected_Proc" & Integer'Image (This.A) & Integer'Image (This.B));`\
`    Private_Proc (X);`\
`  `` Protected_Proc;`\
\
` CPP;`

We see that, due to the construction, the private procedure is not a
primitive operation.

Let\'s define a child class so that the protected operation can be
reached:

` CPP.Child `\
` `\
`  `` Do_It (X: Complete_Type);  -- not primitive`\
\
` CPP.Child;`

A child can look inside the private part of the parent and thus can see
the protected procedure:

` Ada.Text_IO;`\
\
` `` CPP.Child `\
\
`  `` Do_It (X: Complete_Type) `\
`  `\
`    Ada.Text_IO.Put_Line ("Do_It" & Integer'Image (X.A) & Integer'Image (X.B));`\
`    Protected_Proc (X);`\
`  `` Do_It;`\
\
` CPP.Child;`

This is a simple test program, its output is shown below.

` CPP.Child;`\
`  CPP.Child, CPP;`\
\
` Test_CPP `\
\
`  X, Y: Complete_Type;`\
\
\
\
`  X.A := +1;`\
`  Y.A := -1;`\
\
`  Public_Proc (X);  Do_It (X);`\
`  Public_Proc (Y);  Do_It (Y);`\
\
`  X := Y;`\
\
`  Public_Proc (X);  Do_It (X);`\
\
` Test_CPP;`

This is the commented output of the test program:

`Initialize TRUE                     Test_CPP: Initialize X`\
`Initialize TRUE                                      and Y`\
`Public_Proc 1                       |  Public_Proc (X):  A=1`\
`Do_It 1-1073746208                  |  Do_It (X):        B uninitialized`\
`Adjust TRUE                         |  |  Protected_Proc (X): Adjust local copy X of This`\
`Protected_Proc 1-1073746208         |  |  |`\
`Private_Proc 1-1073746208 TRUE      |  |  |  Private_Proc on local copy of This`\
`Finalize TRUE                       |  |  Protected_Proc (X): Finalize local copy X`\
`Public_Proc-1                       |  ditto for Y`\
`Do_It-1 65536                       |  |`\
`Adjust TRUE                         |  |`\
`Protected_Proc-1 65536              |  |`\
`Private_Proc-1 65536 TRUE           |  |`\
`Finalize TRUE                       |  |`\
`Finalize TRUE                       |  Assignment: Finalize target X.P.C`\
`Adjust TRUE                         |  |           Adjust: deep copy`\
`Public_Proc-1                       |  again for X, i.e. copy of Y`\
`Do_It-1 65536                       |  |`\
`Adjust TRUE                         |  |`\
`Protected_Proc-1 65536              |  |`\
`Private_Proc-1 65536 TRUE           |  |`\
`Finalize TRUE                       |  |`\
`Finalize TRUE                       Finalize Y`\
`Finalize TRUE                            and X`

You see that a direct translation of the C++ behaviour into Ada is
difficult, if feasible at all. Methinks, the primitive Ada subprograms
corresponds more to virtual C++ methods (in the example, they are not).
Each language has its own idiosyncrasies which have to be taken into
account, so that attempts to directly translate code from one into the
other may not be the best approach.

### De-encapsulation: friends and stream input-output

In C++, a friend function or class can see all members of the class it
is a friend of. Friends break encapsulation and are therefore to be
discouraged. In Ada, since packages and not classes are the unit of
encapsulation, a \"friend\" subprogram is simply one that is declared in
the same package as the tagged type.

In C++, stream input and output are the particular case where friends
are usually necessary:

``` c++
 #include <iostream>
 class C {
 public:
    C();
    friend ostream& operator<<(ostream& output, C& arg);
 private:
    int a, b;
    bool c;
 };

 #include <iostream>
 int main() {
    C object;
    cout << object;
    return 0;
 };
```

Ada does not need this construct because it defines stream input and
output operations by default: The default implementation of the `Input`,
`Output`, `Read` and `Write` attributes may be overridden (shown for
`Write` as an example). The overriding must occur before the type is
frozen, i.e. (in the case of this example) in the package specification.

` `` Ada``Streams``  `\
` P `\
`   `` C `` `` `\
\
`   `` C `` `` `\
`      A`` B `` Integer`\
`      C `` Boolean`\
`   `` `\
`   `` My_Write ``Stream `` `` `` `` Ada``Streams``Root_Stream_Type`\
`                       Item   `` `` C`\
`   `` C`` `` My_Write``  `\
` P`

By default, the `Write` attribute sends the components to the stream in
the same order as given in the declaration, i.e. A, B then C, so we
change the order.

` `` P `\
`   `` My_Write ``Stream `` `` `` `` Ada``Streams``Root_Stream_Type`\
`                       Item `` `` C`` `\
`   `\
`      `\
`      Boolean`` ``Stream`` Item``C``  `\
`      Integer`` ``Stream`` Item``B``  `\
`      Integer`` ``Stream`` Item``A``  `\
`   `` My_Write`\
` P`

Now `P.C'Write` calls the overridden version of the package.

` `` Ada``Text_IO``Text_Streams`\
` `` P`\
` `` Main `\
`    Object `` P``C`\
` `\
`    P``C`` ``Ada``Text_IO``Text_Streams``Stream ``Ada``Text_IO``Standard_Output`\
`               Object`\
` `` Main`

Note that the stream IO attributes are not primitive operations of the
tagged type; this is also the case in C++ where the friend operators are
not, in fact, member functions of the type.

### Terminology

  Ada                                      C++
  ---------------------------------------- ------------------------------------------------------------------------------------------------------------------
  Package                                  class (as a unit of encapsulation)
  Tagged type                              class (of objects) (as a type) (*not* pointer or reference, which are class-wide)
  Primitive operation                      virtual member function
  Tag                                      pointer to the virtual table
  Class (of types)                         a tree of classes, rooted by a base class and including all the (recursively-)derived classes of that base class
  Class-wide type                          \-
  Class-wide operation                     static member function
  Access value to a specific tagged type   \-
  Access value to a class-wide type        pointer or reference to a class

## See also

### Wikibook

-   Ada Programming
-   Ada
    Programming/Types/record
-   record
-   interface
-   tagged

### Wikipedia

-   Object-oriented
    programming

### Ada Reference Manual

#### Ada 95

-
-
-
-
-
-
#### Ada 2005

-
-
-
-
-
-
-
### Ada Quality and Style Guide

-

es:Programación en Ada/Tipos
etiquetados


# Ada Programming/Contract Based Programming

## Contract Based Programming in Ada 2012

Among the additions to Ada 2012, a number of aspects follow the common
theme of 'formal' contracts on types and subprograms. The formality here
is referring to symbolic logic integrated with existing features of Ada.
Contracts endow the language with expressive features similar to those
of Eiffel\'s Design by Contract™, SPARK, or those connected with
LSP.

Since specifying contracts involves several parts of the Ada language,
also since obeying contracts on the part of the compiler does so, too,
the topic of contracts is addressed in several parts of the language
reference. A comprehensive, more focused view, is a subject of the
latest edition of the Ada Rationale.[^1]

Parts of the contracts can be about statically known properties of the
program, while others would be checked only at run-time. In the first
case, the formal parts of the contract may be analyzed not just by the
Ada compiler, but also by proof tools. The assurance resulting from the
analysis can be that certain undesirable properties will be absent from
the program. For example, the program might then be known to not raise
exceptions.

This overview will only outline syntax and variants by example while
referring to existing wikibook entries and other resources for
explanations of contracts in general.

### Preconditions and Postconditions of Subprograms

Considering functions, for example, their specification gives the type
of the return value as part of the parameter profile. One way of
informing about the specifics of the return value of the function is to
give a mathematical (in style) expression of the result, which is thus
guaranteed by this clause of the contract. A contract may also specify
conditions that say what must be true of objects entering the
computation in order for the function to produce its result. In
contracts, the return value is named *function_name*`'Result`.

`  `` Sum (A, B : Number) `` Number`\
`  `\
`    Post => (`\
`               A <= 0.0 `` B >= 0.0`\
`             `\
`               Sum'Result = A + B);`

An alternative mode of expression emphasizes the pre-requisites,

`  `` Sum (A, B : Number) `` Number`\
`  `\
`    Pre  => A <= 0.0 and B >= 0.0,`\
`    Post => Sum'Result = A + B;`

The first example leaves unsaid what happens when the condition
evaluates to False. By default, when an assertion fails, and if the
current Assertion_Policy is Check, Assertion_Error is raised. (The
current amendment process of Ada is considering "raise expressions"
(8652/0117): should the condition not be True, these permit raising a
specific exception as an  part, with a
corresponding specific message instead of defaulting as just outlined.)
The second example expressly obliges, in `Pre`, the caller to ensure
that both `A` and `B` will have the specified properties of being
`Number`s and of being no greater than 0.0 and no less than 0.0,
respectively. This way the `Pre` aspect is stating that in case the
condition is False, the function cannot fulfill its contractual
obligation as given in `Post`.

### Assertions About Types And Subtypes

Ada types may be declared to have a type invariant. This kind of
predicate applies to private types. Hence, its expression may only refer
to other publicly visible features of the type. The type\'s name here
denotes the current instance of the type.

`  `` Stack `` `\
`      `` Type_Invariant => Count(Stack) >= 0;`

As detailed in
, invariants
may also be given for a derivation class of types, using aspect name
`Type_Invariant'Class`, to apply to all types in a hierarchy.

A predicate may also be given when declaring a subtype. In this case,
the expression (of a boolean type) states properties of the subtype (see
 for
details) and its truth would be checked at certain points. When a
predicate should be tested by the compiler, its aspect is named
`Static_Predicate`, and `Dynamic_Predicate` otherwise. Roughly, then,
checks are performed when a type conversion takes place, or when a
parameter is passed, or when an object is created.

When deriving subtypes, the predicate that applies is the conjunction of
the predicates on the subtypes involved.

### Assertion Policies

The language reference manual extends the `Assert` pragma and its
associated `Assertion_Policy` to also cover aspects of contract based
programming in
.
Each 'section' of a contract, such as `Pre`, can be turned on and off
for checking. This is done by specifying the desired Assertion_Policy,
as locally or as globally as is desired. The following line turns checks
on for aspect mark `Pre`:

`  `` Assertion_Policy (Pre => Check);`

Implementations of Ada are free to provide more policy identifiers than
the two defined by the language, `Check` and `Ignore`.

A setting that affects all possible assertion aspects at the same time
omits giving aspect marks.

`  `` Assertion_Policy (Check);`

## References

[^1]: Ada Rationale, Contracts and
    Aspects


# Ada Programming/Ada 2005

This is an overview of the major features that are available in **Ada
2005**, the version of the Ada standard that was accepted by ISO in
January 2007 (to differentiate it from its predecessors Ada
83 and Ada
95, the informal name Ada 2005 is
generally agreed on). For the rationale and a more detailed (and very
technical) description, see the
Amendment to the Ada
Reference Manual following the links to the last version of every Ada
Issue document (AI).

Although the standard is now published, not all compilers will be able
to handle it. Many of these additions are already implemented by the
following Free Software compilers:

-   GNAT GPL Edition
-   GCC 4.1
-   GNAT Pro 6.0.2 (the AdaCore
    supported version) is a complete implementation.

After downloading and installing any of them, remember to use the
`-gnat05` switch when compiling Ada 2005 code. Note that Ada 2005 is the
default mode in GNAT GPL 2007 Edition.

## Language features

### Character set

Not only does Ada 2005 now support a new 32-bit character type ---
called `Wide_Wide_Character` --- but the source code itself may be of
this extended character set as well. Thus Russians and Indians, for
example, will be able to use their native language in identifiers and
comments. And mathematicians will rejoice: The whole Greek and fractur
character sets are available for identifiers. For example,
Ada.Numerics will
be extended with a new constant:

`π : `` := Pi;`

This is not a new idea --- GNAT always had the
`-gnati`*`c`* compiler option to specify the character set
1.
But now this idea has become standard, so all Ada compilers will need to
support Unicode 4.0 for identifiers --- as the
new standard requires.

See also:

-
-
### Interfaces

Interfaces allow for a limited form of multiple inheritance similar to
Java and C#.

You find a full description here: Ada
Programming/OO.

See also:

-
-
### Union

In addition to Ada\'s safe variant record an unchecked C style union is
now available.

You can find a full description here: Ada
Programming/Types/record#Union.

See also:

-
-
### With

The with statement got a massive upgrade. First there is the new
limited with which
allows two packages to *with* each other. Then there is private
with to make a
package only visible inside the private part of the specification.

See also:

-
-
### Access types

#### Not null access

An access type definition can specify that the access type can never be
null.

See Ada Programming/Types/access#Null
exclusions.

See also:

#### Anonymous access

The possible uses of anonymous access types are extended. They are
allowed virtually in every type or object definition, including access
to subprogram parameters. Anonymous access types may point to constant
objects as well. Also, they could be declared to be not null.

With the addition of the following operations in package
, it is possible to test the
equality of anonymous access types.

`   `` "=" (Left, Right : `*`universal_access`*`) `` Boolean;`\
`   `` "/="(Left, Right : `*`universal_access`*`) `` Boolean;`

See Ada Programming/Types/access#Anonymous
access.

See also:

-
-
-
## Language library

### Containers

A major addition to the language library is the generic packages for
containers. If you are familiar with the C++ STL, you will likely feel
very much at home using .
One thing, though: Ada is a block structured language. Many ideas of how
to use the STL employ this feature of the language. For example, local
subprograms can be supplied to iteration schemes.

The original Ada Issue text
 has now been
transformed into .

If you know how to write Ada programs, and have a need for vectors,
lists, sets, or maps (tables), please have a look at the
 mentioned above. There is
an *!example* section in the text explaining the use of the containers
in some detail. Matthew Heaney provides a number of demonstration
programs with his reference implementation of AI-302
() which you can find at
tigris.

In Ada Programming/Containers
you will find a demo using containers.

**Historical side note**: The C++ STL draws upon the work of David R.
Musser and Alexander A. Stepanov. For some of their studies of generic
programming, they had been using Ada 83. The Stepanov Papers
Collection has a few publications
available.

### Scan Filesystem Directories and Environment Variables

See also:

-
-
### Numerics

Besides the new constant of package
 (see Character
Set above), the most
important addition are the packages to operate with vectors and
matrices.

See also:

-
-
(Related note on Ada programming tools: AI-388 contains an interesting
assessment of how compiler writers are bound to perpetuate the lack of
handling of international characters in programming support tools for
now. As an author of Ada programs, be aware that your tools provider or
Ada consultant could recommend that the program text be 7bit ASCII
only.)

## Real-Time and High Integrity Systems

See also:

-
-
-
-
-
### Ravenscar profile

See also:

-
-
-
-
### New scheduling policies

See also:

-
-
-
### Dynamic priorities for protected objects

See also:

## Summary of what\'s new

### New keywords

Added 3 keywords (72 total)

-
-
-
### New pragmas

Added 11 pragmas:

-
-
-
-
-
-
-
-
-
-
-
### New attributes

Added 7 attributes:

-
-
-
-
-
-
-
### New packages

-   Assertions:
    -
```{=html}
<!-- -->
```
-   Container library:
    -
    -
    -
    -           `<small>`{=html}(generic procedure)`</small>`{=html}

    -           `<small>`{=html}(generic procedure)`</small>`{=html}

    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
```{=html}
<!-- -->
```
-   Vector and matrix manipulation:
    -
    -
    -
    -
```{=html}
<!-- -->
```
-   General OS facilities:
    -
    -
    -
```{=html}
<!-- -->
```
-   String hashing:
    -           `<small>`{=html}(generic function)`</small>`{=html}

    -           `<small>`{=html}(generic function)`</small>`{=html}

    -           `<small>`{=html}(generic function)`</small>`{=html}

    -           `<small>`{=html}(generic function)`</small>`{=html}

    -           `<small>`{=html}(generic function)`</small>`{=html}

    -           `<small>`{=html}(generic function)`</small>`{=html}

    -           `<small>`{=html}(generic function)`</small>`{=html}

    -           `<small>`{=html}(generic function)`</small>`{=html}

    -           `<small>`{=html}(generic function)`</small>`{=html}

    -           `<small>`{=html}(generic function)`</small>`{=html}

    -           `<small>`{=html}(generic function)`</small>`{=html}

    -           `<small>`{=html}(generic function)`</small>`{=html}

```{=html}
<!-- -->
```
-   Time operations:
    -
    -
    -
```{=html}
<!-- -->
```
-   Tagged types:
    -           `<small>`{=html}(generic function)`</small>`{=html}

```{=html}
<!-- -->
```
-   Text packages:
    -
    -
    -
    -
    -
    -
    -
```{=html}
<!-- -->
```
-   `Wide_Wide_Character` packages:
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
```{=html}
<!-- -->
```
-   Execution-time clocks:
    -
    -
    -
```{=html}
<!-- -->
```
-   Dispatching:
    -
    -
    -
```{=html}
<!-- -->
```
-   Timing events:
    -
```{=html}
<!-- -->
```
-   Task termination procedures:
    -
## See also

### Wikibook

-   Ada Programming/Ada 83
-   Ada Programming/Ada 95
-   Ada Programming/Ada 2012
-   Ada Programming/Object
    Orientation
-   Ada
    Programming/Types/access
-   Ada Programming/Keywords
-   Ada
    Programming/Keywords/and
-   Ada
    Programming/Keywords/interface
-   Ada Programming/Attributes
-   Ada Programming/Pragmas
-   Ada
    Programming/Pragmas/Restrictions
-   Ada
    Programming/Libraries/Ada.Containers
-   Ada
    Programming/Libraries/Ada.Directories

### Pages in the category Ada 2005

-   Ada Programming}}/Ada 2005 feature

## External links

### Papers and presentations

-   Ada 2005: Putting it all
    together
    (SIGAda 2004 presentation)
-   GNAT and Ada 2005
    (SIGAda 2004 paper)
-   An invitation to Ada
    2005,
    and the presentation of this
    paper
    at Ada-Europe 2004

### Rationale

-   *Rationale for Ada
    2005* by
    John
    Barnes "wikilink"):
    1.  Introduction
    2.  Object Oriented Model
    3.  Access Types
    4.  Structure and Visibility
    5.  Tasking and Real-Time
    6.  Exceptions, Generics, Etc.
    7.  Predefined Library
    8.  Containers
    9.  Epilogue

:

    :   References
    :   Index

Available as a single document for
printing.

### Language Requirements

-   *Instructions to the Ada Rapporteur Group from SC22/WG9 for
    Preparation of the Amendment to ISO/IEC
    8652* (10 October
    2002), and a presentation of this
    document at SIGAda 2002

### Ada Reference Manual

-   **Ada Reference Manual**, ISO/IEC 8652:1995(E) with COR.1:2001 and
    AMD.1:2007
-   **Annotated Ada Reference Manual**, ISO/IEC 8652:1995(E) with
    COR.1:2001 and
    AMD.1:2007
    (colored diffs)
-   List of Ada Amendment
    drafts

### Ada Issues

-   Amendment 200Y
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
2005 Ada Programming}}/Ada 2005\| \*Ada
2005 Ada Programming}}/Ada 2005 feature\|
\*Ada 2005


# Ada Programming/Ada 2012

This is an overview of the major features that are available in **Ada
2012**, the most recent version of the Ada standard.

## Summary of what\'s new

### New syntax

Added 4 forms of expressions:

-   conditional expressions
-   case expressions
-   quantified expressions
-   expression functions

These additional expressions
originated with new support for contract based
programming.

### New keywords

Added 1 keyword (73 total)

-
### New pragmas

Added 5 pragmas:

-
-
-
-
-
Note that all these pragmas except
 born obsolescent,
and it is recommended to use them as aspects
instead.

### New aspects

Aspect specifications is a new
feature of Ada 2012. While some aspect identifiers are completely new,
others were present in previous versions of the language as
aspect-related pragmas or attribute-definition clauses. Note that for
these pragmas, in some cases the old pragma identifiers are marked as
obsolescent, while in other cases the usage of the pragma is still the
recommended approach.

Added 18 aspects:

-
-       (also added as an obsolescent pragma)

-
-
-
-
-       (also added as an obsolescent pragma)

-
-
-       (also added as an obsolescent pragma)

-       (also added as an obsolescent pragma)

-
-
-
-
-
-
-
Aspect specifications already present in previous versions of the
language as pragmas:

-
-       (pragma now obsolescent)

-       (pragma now obsolescent)

-       (pragma now obsolescent)

-       (pragma now obsolescent)

-       (pragma now obsolescent)

-
-       (pragma now obsolescent)

-
-
-       (pragma now obsolescent)

-       (pragma now obsolescent)

-       (pragma now obsolescent)

-       (pragma now obsolescent)

-
-       (pragma now obsolescent)

-
-       (pragma now obsolescent)

-
-       (pragma now obsolescent)

-
-       (pragma now obsolescent)

-
-
-
-       (pragma now obsolescent)

-       (pragma now obsolescent)

-       (pragma now obsolescent)

-       (pragma now obsolescent)

Aspect specifications already present in previous versions of the
language as attribute definition clauses:

-
-
-
-
-
-
-
-
-
-
-
-
-
### New attributes

Added 5 attributes:

-
-
-
-
-
### New packages

-   Multiprocessing:
    -
    -
```{=html}
<!-- -->
```
-   Real-time:
    -
```{=html}
<!-- -->
```
-   OS facilities:
    -
```{=html}
<!-- -->
```
-   Iterators:
    -
```{=html}
<!-- -->
```
-   Text handling:
    -
    -
    -
```{=html}
<!-- -->
```
-   Container library:
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
## See also

### Wikibook

-   Ada Programming/Ada 83
-   Ada Programming/Ada 95
-   Ada Programming/Ada 2005

### Pages in the category Ada 2012

-   Ada Programming}}/Ada 2012 feature

## External links

-   www.ada2012.org, website maintained by
    the Ada Resource Association.
-   Ada Answers: Ada
    2012
-   ISO/IEC JTC1/SC22/WG9 N498 (2009). *Instructions to the Ada
    Rapporteur Group from SC22/WG9 for Preparation of Amendment 2 to
    ISO/IEC 8652*

### Papers and presentations

-   Towards Ada 2012: an interim report from the Ada Rapporteur
    Group,
    by Ed Schonberg (2010-06-17)
-   HD Video: *An introduction to Ada
    2012*, presentation by
    Ed Schonberg (1h 02 min, 2012-10-16)

### Rationale

-   *Ada 2012
    Rationale*,
    by John Barnes "wikilink")
    -   Introduction
    -   Chapter 1: Contracts and
        Aspects
    -   Chapter 2:
        Expressions
    -   Chapter 3: Structure and
        Visibility
    -   Chapter 4: Tasking and
        Real-Time
    -   Chapter 5: Iterators, Pools,
        etc.
    -   Chapter 6:
        Containers
    -   Epilogue
    -   Predefined
        Library

### Ada Reference Manual

-   **Ada Reference Manual**, ISO/IEC 8652:2012(E) --- Language and
    Standard
    Libraries
    -   ISO/IEC 8652:2012 --- Information technology --- Programming
        languages ---
        Ada
        (2012-12-10), same contents as the above link.
-   **Annotated Ada Reference Manual**, ISO/IEC 8652:2012(E) ---
    Language and Standard
    Libraries
    (colored diffs)
-   List of Ada Amendment
    drafts

### Ada Issues

-   Ada 2005 Issues
    -
    -
    -
### Implementations

-   Implementation of Ada 2012
    Features
    in GNAT compiler

### Press releases

-   Ada 2012 Language Standard Approved by
    ISO,
    by Ada Resource Association & Ada-Europe (2012-12-18)
    PDF
-   Ada 2012 Language Standard Submitted to
    ISO,
    by Ada Resource Association & Ada-Europe (2012-06-12)
    PDF

2012 Ada Programming}}/Ada 2012\| \*Ada
2012 Ada Programming}}/Ada 2012 feature\|


# Ada Programming/Containers

What follows is a simple demo of some of the container types. It does
not cover everything, but should get you started.

#### First Example: Maps

The program below prints greetings to the world in a number of human
languages. The greetings are stored in a table, or hashed map. The map
associates every greeting (a value) with a language code (a key). That
is, you can use language codes as keys to find greeting values in the
table.

The elements in the map are constant strings of international
characters, or really, pointers to such constant strings. A package
`Regional` is used to set up both the language IDs and an instance of
.

` `

` ``;  `` Ada.Containers;`\
\
` Regional `\
\
`   `` Language_ID `` (DE, EL, EN, ES, FR, NL);`\
`   `\
\
`   `` Hello_Text `` `` `` Wide_String;`\
`   `\
\
\
`   `` ID_Hashed (id: Language_ID) `` Hash_Type;`\
`   `\
\
`   `` Phrases `` `` Ada.Containers.Hashed_Maps`\
`     (Key_Type => Language_ID,`\
`      Element_Type => Hello_Text,`\
`      Hash => ID_Hashed,`\
`      Equivalent_Keys => "=");`\
\
` Regional;`

Here is the program, details will be explained later.

` Regional; `` Regional;`\
` ``; `` Ada;`\
\
` Hello_World_Extended `\
\
`   `\
\
`   greetings: Phrases.Map;`\
`   `\
\
` `\
\
`   Phrases.Insert(greetings,`\
`                  Key => EN,`\
`                  New_Item => `` Wide_String'("Hello, World!"));`\
\
`   `\
`   greetings.Insert(DE, `` Wide_String'("Hallo, Welt!"));`\
`   greetings.Insert(NL, `` Wide_String'("Hallo, Wereld!"));`\
`   greetings.Insert(ES, `` Wide_String'("¡Hola mundo!")); `\
`   greetings.Insert(FR, `` Wide_String'("Bonjour, Monde!"));`\
`   greetings.Insert(EL, `` Wide_String'("Γεια σου κόσμε"));`\
\
`   `\
`      `` Phrases;`\
\
`      speaker: Cursor := First(greetings);`\
`   `\
`      `` Has_Element(speaker) `\
`         Wide_Text_IO.Put_Line( Element(speaker).`` );`\
`         Next(speaker);`\
`      `` ``;`\
`   ``;`\
\
` Hello_World_Extended;`

The first of the `Insert` statements is written in an Ada 95 style:

`  Phrases.Insert(greetings,`\
`                 Key => EN,`\
`                 New_Item => `` Wide_String'("Hello, World!"));`

The next insertions use so called distinguished receiver notation which
you can use in Ada 2005. (It\'s O-O parlance. While the Insert call
involves all of: a Container object (greetings), a Key object (EN), and
a New_Item object (
Wide_String\'(\"Hello, World!\")), the Container object is distinguished
from the others in that the Insert call provides it (and only it) with
the other objects. In this case the Container object will be modified by
the call, using arguments named Key and New_Item for the modification.)

`  greetings.Insert(ES, `` Wide_String'("¡Hola mundo!"));`

After the table is set up, the program goes on to print all the
greetings contained in the table. It does so employing a cursor that
runs along the elements in the table in some order. The typical scheme
is to obtain a cursor, here using `First`, and then to iterate the
following calls:

1.  `Has_Element`, for checking whether the cursor is at an element
2.  `Element`, to get the element and
3.  `Next`, to move the cursor to another element

When there is no more element left, the cursor will have the special
value `No_Element`. Actually, this is an iteration scheme that can be
used with all containers in child packages of
.

#### A slight variation: picking an element

The next program shows how to pick a value from the map, given a key.
Actually, you will provide the key. The program is like the previous
one, except that it doesn\'t just print all the elements in the map, but
picks one based on a Language_ID value that it reads from standard
input.

` Regional; `` Regional;`\
` Ada.Wide_Text_IO; `` Ada;`\
\
` Hello_World_Pick `\
\
`  ... as before ...`\
\
` `\
`     `` Phrases;`\
` `\
`     `` Lang_IO `` `` Wide_Text_IO.Enumeration_IO(Language_ID);`\
`     lang: Language_ID;`\
`  `\
`     Lang_IO.Get(lang);`\
`     Wide_Text_IO.Put_Line( greetings.Element(lang).`` );`\
`  ``;`\
` `\
` Hello_World_Pick;`

This time the `Element` function consumes a Key (lang) not a Cursor.
Actually, it consumes two values, the other value being `greetings`, in
distinguished receiver notation.

#### Second Example: Vectors and Maps

Let\'s take bean counting literally. Red beans, green beans, and white
beans. (Yes, white beans really do exist.) Your job will be to collect a
number of beans, weigh them, and then determine the average weight of
red, green, and white beans, respectively. Here is one approach.

Again, we need a package, this time for storing vegetable related
information. Introducing the `Beans` package (the Grams type doesn\'t
belong in a vegetable package, but it\'s there to keep things simple):

` `\
\
` Beans `\
\
`   `` Bean_Color `` ``R`` G`` W`\
`   `\
\
`   `` Grams `` `` 0``01 `` 7`\
`   `\
`   `\
\
`   `` Bean `\
`   `\
`      `\
`         kind`` Bean_Color`\
`         weight`` Grams`\
`      `` `\
\
`   `` Bean_Count `` Positive `` 1 `` 1_000`\
`   `\
\
`   `` Bean_Vecs `` `` Ada``Containers``Vectors`\
`     ``Element_Type => Bean`\
`      Index_Type => Bean_Count`\
\
` Beans`

The `Vectors` instance offers a data structure similar to an array that
can change its size at run time. It is called `Vector`. Each bean that
is read will be appended to a `Bean_Vecs.Vector` object.

The following program first calls `read_input` to fill a buffer with
beans. Next, it calls a function that computes the average weight of
beans having the same color. This function:

` Beans``   `` Beans`\
\
` average_weight`\
`  ``buffer`` Bean_Vecs``Vector`` desired_color`` Bean_Color`` `` Grams`\
``{{Ada/comment | scan `buffer` for all beans that have `desired_color`. Compute the}}``{=mediawiki}\
``{{Ada/comment | mean of their `.weight` components}}``{=mediawiki}

Then the average value is printed for beans of each color and the
program stops.

` Beans`\
` average_weight`\
` `\
\
` bean_counting `\
`   `` Beans`` Ada`\
\
`   buffer`` Bean_Vecs``Vector`\
\
`   `` read_input``buf`` `` `` Bean_Vecs``Vector`` `` `\
`   ```{{Ada/comment | collect information from a series of bean measurements into `buf`}}``{=mediawiki}\
\
\
` `\
\
`   read_input``buffer`\
\
`   `\
`   ```{{Ada/comment | For every bean color in `Bean_Color`, the function `average_weight`}}``{=mediawiki}\
`   ```{{Ada/comment | will scan `buffer` once, and accumulate statistical data from}}``{=mediawiki}\
`   `\
\
`   `` kind `` Bean_Color `\
`      Wide_Text_IO``Put_Line`\
`        ``Bean_Color``Wide_Image``kind`` `\
`         " ø =" `` Grams``Wide_Image`` average_weight``buffer`` kind`` `\
`   `` `\
\
` bean_counting`

All container operations take place in function `average_weight`. To
find the mean weight of beans of the same color, the function is looking
at all beans in order. If a bean has the right color, `average_weight`
adds its weight to the total weight, and increases the number of beans
counted by 1.

The computation visits all beans. The iteration that is necessary for
going from one bean to the next and then performing the above steps is
best left to the `Iterate` procedure which is part of all container
packages. To do so, wrap the above steps inside some procedure and pass
this procedure to `Iterate`. The effect is that `Iterate` calls your
procedure for each element in the vector, passing a cursor value to your
procedure, one for each element.

Having the container machinery do the iteration can also be faster than
moving and checking the cursor yourself, as was done in the
`Hello_World_Extended` example.

` Beans``  `` Beans``Bean_Vecs`\
\
` average_weight`\
`  ``buffer`` Bean_Vecs``Vector`` desired_color`` Bean_Color`` `` Grams`\
\
`   total`` Grams := 0``0`\
`   ```{{Ada/-- | weight of all beans in `buffer` having `desired_color`}}``{=mediawiki}\
\
`   number`` Natural := 0`\
`   ```{{Ada/-- | number of beans in `buffer` having `desired_color`}}``{=mediawiki}\
\
`   `` accumulate``c`` Cursor`` `\
`      ```{{Ada/-- | if the element at `c` has the `desired_color`, measure it}}``{=mediawiki}\
`   `\
`      `` Element``c``kind = desired_color `\
`         number := number `` 1`\
`         total := total `` Element``c``weight`\
`      `` `\
`   `` accumulate`\
\
` `\
\
`   Iterate``buffer`` accumulate``Access`\
\
`   `` number `` 0 `\
`      `` total `` number`\
`   `\
`      `` 0``0`\
`   `` `\
\
` average_weight`

This approach is straightforward. However, imagine larger vectors.
`average_weight` will visit all elements repeatedly for each color. If
there are M colors and N beans, `average_weight` will be called M \* N
times, and with each new color, N more calls are necessary. A possible
alternative is to collect all information about a bean once it is
visited. However, this will likely need more variables, and you will
have to find a way to return more than one result (one average for each
color), etc. Try it!

A different approach might be better. One is to copy beans of different
colors to separate vector objects. (Remembering Cinderella.) Then
`average_weight` must visit each element only one time. The following
procedure does this, using a new type from `Beans`, called `Bean_Pots`.

`   ...`\
`   `` Bean_Pots `` ``Bean_Color`` `` Bean_Vecs``Vector`\
`   ...`

Note how this plain array associates colors with Vectors. The procedure
for getting the beans into the right bowls uses the bean color as array
index for finding the right bowl (vector).

` gather_into_pots``buffer`` Bean_Vecs``Vector`` pots`` `` `` Bean_Pots`` `\
`   `` Bean_Vecs`\
\
`   `` put_into_right_pot``c`` Cursor`` `\
`      ```{{Ada/comment | select the proper bowl for the bean at `c` and «append»}}``{=mediawiki}\
`      `\
`   `\
`      Append``pots``Element``c``kind`` Element``c`\
`   `` put_into_right_pot`\
\
`  `\
`   Iterate``buffer`` put_into_right_pot``Access`\
` gather_into_pots`

Everything is in place now.

` Beans`\
` average_weight`\
` gather_into_pots`\
` Ada``Wide_Text_IO`\
\
` bean_counting `\
`   `` Beans`` Ada`\
\
`   buffer`` Bean_Vecs``Vector`\
`   bowls`` Bean_Pots`\
\
`   `` read_input``buf`` `` `` Bean_Vecs``Vector`` `` `\
`   ```{{Ada/-- | collect information from a series of bean measurements into `buf`}}``{=mediawiki}\
\
\
` `\
\
`   read_input``buffer`\
\
`   `\
`   `\
`   `\
\
`   gather_into_pots``buffer`` bowls`\
\
`   `` color `` Bean_Color `\
`      Wide_Text_IO``Put_Line`\
`        ``Bean_Color``Wide_Image``color`\
`         & " ø ="`\
`         & Grams``Wide_Image``average_weight``bowls``color`` color`\
`   `` `\
\
` bean_counting`

As a side effect of having chosen one vector per color, we can determine
the number of beans in each vector by calling the `Length` function. But
`average_weight`, too, computes the number of elements in the vector.
Hence, a summing function might replace `average_weight` here.

#### All In Just One Map!

The following program first calls `read_input` to fill a buffer with
beans. Then, information about these beans is stored in a table, mapping
bean properties to numbers of occurrence. The processing that starts at
`Iterate` uses chained procedure calls typical of the
 iteration mechanism.

The Beans package in this example instantiates another generic library
unit, . Where
the  require a
hashing function,
 require a
comparison function. We provide one, `"<"`, which sorts beans first by
color, then by weight. It will automatically be associated with the
corresponding generic formal function, as its name, `"<"`, matches that
of the generic formal function, `"<"`.

`   ...`\
`   `` "<"``a`` b`` Bean`` `` Boolean`\
`   `\
\
`   `` Bean_Statistics`\
`     `\
`     `\
`   `` `` Ada``Containers``Ordered_Maps`\
`     ``Element_Type => Natural`\
`      Key_Type => Bean`\
`   ...`

Where the previous examples have ed
subprograms, this variation on `bean_counting` packs them all as local
subprograms.

` Beans`\
` Ada``Wide_Text_IO`\
\
` bean_counting `\
`   `` Beans`` Ada`\
\
`   buffer`` Bean_Vecs``Vector`\
`   stats_cw`` Bean_Statistics``Map`\
`   `\
`   `\
\
`   `` read_input``buf`` `` `` Bean_Vecs``Vector`` `` `\
`   ```{{Ada/-- | collect information from a series of bean measurements into `buf`}}``{=mediawiki}\
\
`   `` add_bean_info``specimen`` `` Bean`\
`   ```{{Ada/-- | insert bean `specimen` as a key into the `stats_cw` table unless}}``{=mediawiki}\
`   `\
`   `\
\
`   `` add_bean_info``specimen`` `` Bean`` `\
\
`      `` one_more``b`` `` Bean`` n`` `` `` Natural`` `\
`       `\
`      `\
`         n := n `` 1`\
`      `` one_more`\
\
`      c `` Bean_Statistics``Cursor`\
`      inserted`` Boolean`\
`   `\
`      stats_cw``Insert``specimen`` 0`` c`` inserted`\
`      Bean_Statistics``Update_Element``c`` one_more``Access`\
`   `` add_bean_info`\
\
` `\
\
`   read_input``buffer`\
\
`   ```{{Ada/-- | next, for all beans in the vector `buffer` just filled, store}}``{=mediawiki}\
`   ```{{Ada/-- | information about each bean in the `stats_cw` table.}}``{=mediawiki}\
\
`   `\
`      `` Bean_Vecs`\
\
`      `` count_bean``c`` Cursor`` `\
`      `\
`         add_bean_info``Element``c`\
`      `` count_bean`\
`   `\
`      Iterate``buffer`` count_bean``Access`\
`   `\
\
`   `\
`   `\
`   ```{{Ada/-- | The `First`, and `Ceiling` functions will find cursors}}``{=mediawiki}\
`   `\
\
\
`   `\
`      `` Bean_Statistics`\
\
`      `\
\
`      q_sum`` Grams`\
`      q_count`` Natural`\
\
`      `` q_stats``lo`` hi`` Cursor`\
`      ```{{Ada/-- | `q_stats` will update the `q_sum` and `q_count` globals with}}``{=mediawiki}\
`      ```{{Ada/-- | the sum of the key weights and their number, respectively. `lo`}}``{=mediawiki}\
`      ```{{Ada/-- | (included) and `hi` (excluded)  mark the interval of keys}}``{=mediawiki}\
`      `\
\
`      `` q_stats``lo`` hi`` Cursor`` `\
`         k`` Cursor := lo`\
`      `\
`         q_count := 0`` q_sum := 0``0`\
`         `\
`            `` `` k = hi`\
`            q_count := q_count `` Element``k`\
`            q_sum := q_sum `` Key``k``weight `` Element``k`\
`            Next``k`\
`         `` `\
`      `` q_stats`\
\
\
`      `\
`      `` assert`` Is_Empty``stats_cw`` "container is empty"`\
\
`      lower`` upper`` Cursor := First``stats_cw`\
`      `\
`      `\
\
`   `\
\
`      `\
\
`      Wide_Text_IO``Put_Line``"Summary:"`\
\
`      `` color `` Bean_Color `\
`         lower := upper`\
`         `` color = Bean_Color``Last `\
`            upper := No_Element`\
`         `\
`            upper := Ceiling``stats_cw`` Bean``Bean_Color``Succ``color`` 0``0`\
`         `` `\
\
`         q_stats``lower`` upper`\
\
`         `` q_count `` 0 `\
`            Wide_Text_IO``Put_Line`\
`              ``Bean_Color``Wide_Image``color`` & " group:" &`\
`               "  ø =" & Grams``Wide_Image``q_sum `` q_count`` &`\
`               ", # =" & Natural``Wide_Image``q_count`` &`\
`               ", Σ =" & Grams``Wide_Image``q_sum`\
`         `` `\
`      `` `\
`   `\
\
` bean_counting`

Like in the greetings example, you can pick values from the table. This
time the values tell the number of occurrences of beans with certain
properties. The `stats_cw` table is ordered by key, that is by bean
properties. Given particular properties, you can use the `Floor` and
`Ceiling` functions to approximate the bean in the table that most
closely matches the desired properties.

It is now easy to print a histogram showing the frequency with which
each kind of bean has occurred. If N is the number of beans of a kind,
then print N characters on a line, or draw a graphical bar of length N,
etc. A histogram showing the number of beans per color can be drawn
after computing the sum of beans of this color, using groups like in the
previous example. You can delete beans of a color from the table using
the same technique.

Finally, think of marshalling the beans in order starting at the least
frequently occurring kind. That is, construct a vector appending first
beans that have occurred just once, followed by beans that have occurred
twice, if any, and so on. Starting from the table is possible, but be
sure to have a look at the sorting functions of
.

## See also

### Wikibook

-   Ada Programming
-   Ada
    Programming/Libraries/Ada.Containers

### Ada 2005 Reference Manual

-
Programming}}\|Containers