 Ada '83 Rationale, Sec 7.6: The Construction of Private Types

## CHAPTER 7: Derived Types

### 7.6 The Construction of Private Types

For the construction of private types, derived types provide an easy and unambiguous way of distinguishing the operations of the private type from those of the type used for its representation (that is, the type declared by the full type declaration). The relevant aspects are: (1) the fact that the parent and the derived type are distinct types; (2) the fact that explicit conversions between the two types exist.

Consider for example the case where an operation specified for a private type is implemented in terms of an operation of the type that is used for representing the private type:

 ```package LOCKSMITH is type KEY is private; procedure GET_KEY(K : out KEY); ... function "<" (X, Y : KEY) return BOOLEAN; private type KEY is new CHARACTER; ... end; ```

The user need not know that keys are implemented as characters, but he is provided with the operator "<" to order keys. This operator is implemented as the comparison of the corresponding characters:

 ```package body LOCKSMITH is ... function "<" (X, Y : KEY) return BOOLEAN is begin return CHARACTER(X) < CHARACTER(Y); end; ... end LOCKSMITH; ```

The function first converts the parameters X and Y into characters and then compares them using character comparison. (Note that X < Y would not work: it would be a recursive call.)

A more general example of this problem is provided by the following schema

 ```package P is type T is private; function F(X : T) return T; private type T is new REP; there exists a function F operating on REP end P; ```

In order to implement the function F on T by means of that on REP we first convert the parameter to the type REP; then convert the result back to type T.

 ```package body P is ... function F(X : T) return T is begin return T(F(REP(X))); end; ... end; ```

Without derivation, a solution can be developed using one-component records:

 ```package P is type T is private; function F(X : T) return T; private type T is record VALUE : REP; end record; end; package body P is ... function F(X : T) return T is begin return T'(VALUE => F(X.VALUE)); end; ... end; ```

The function F is applied to the single component of the parameter; then a one-component aggregate is returned as the function result. The drawback of this solution is its lack of symmetry. Thus, compare

`    return T(F(REP(X)));`

with

`    return T'(VALUE =>  F(X.VALUE));`

Instead of the succession of two conversions - to REP and then back to T - we have now the succession of component selection (X.VALUE) and of aggregate construction T'(VALUE => ... ). Note that there are already cases where the language requires one-component records (for implicit initializations). For the remaining cases, however, the solution with derived types is more elegant.

NEXTPREVIOUSUPTOCINDEX