# 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
