[Ada Information Clearinghouse]
Ada '83 Rationale, Sec 7.7: Achieving Transitivity of Visibility

"Rationale for the Design of the
Ada® Programming Language"

[Ada '83 Rationale, HTML Version]

Copyright ©1986 owned by the United States Government. All rights reserved.
Direct inquiries to the Ada Information Clearinghouse at adainfo@sw-eng.falls-church.va.us.

CHAPTER 7: Derived Types

7.7 Achieving Transitivity of Visibility

When a derived type is declared, a new type is thereby obtained that is a copy of an existing parent type. The new type derives some operations from the parent type and these derived operations are implicitly declared at the point of declaration of the derived type. This ability to declare a copy of a type can be used to achieve transitivity of visibility. This term will be explained by the following examples. Consider a generic package

generic
  ...
package BASE is
  type T is private;

  function F(X   :  T)     return T;
  function G(X   :  T)     return T;
  ...
  function H(X   :  T)     return T;
  ...
end;

Consider now an application of this package, and let us assume that we now want to build higher-level operations on top of those of BASE. This can be achieved as follows:

with BASE;
package HIGHER_LEVEL is
  package NEW_BASE is new BASE(...);

  type T is new NEW_BASE.T;
  -- this derived type declaration implicitly declares:

  -- function F(X  :  T)   return T;
  -- function G(X  :  T)   return T;
  ...
  -- function H(X  :  T)   return T;

  -- now we declare additional operations on T:

  procedure P(X, Y :  in out T);
  ...
  procedure R(X :  T);
end;

Consider finally a user procedure

with HIGHER_LEVEL; use HIGHER_LEVEL;
procedure USER is
  ...
end;

Within the body of USER the operations directly available on T are the functions F, G, ... , H, and the procedures P, ... , R. The functions are directly visible, without having to write

    use NEW_BASE;

It is in this sense that derivation has achieved transitivity of visibility.

To further emphasize the point, consider a nongeneric formulation of the above problem

package BASE is
  ...
end;

with BASE;
package HIGHER_LEVEL is
  type T is new BASE.T;
  -- implicit declaration of F, G, ... , H

  procedure P(X, Y :  in out T);
  ...
  procedure R(X :  T);
end;

Because of the transitivity achieved by derivation, the procedure USER does not have to mention

    with BASE; use BASE;

The package BASE can thus be considered as a lower-level package ignored by the user.

Note that the controlled transitivity achieved by derivation would not be obtained by subtypes. Consider for example:

with BASE; use BASE;
package HIGHER_LEVEL is
  subtype T is BASE.T;
  procedure P(X, Y :  in out T);
  ...
  procedure R(X :  T);
end;

The effect of the use clause "use BASE;" is not transitive. This means that its effect covers the package HIGHER_LEVEL itself but not packages that mention HIGHER_LEVEL in their context clause.

Another alternative for achieving transitivity is to use renaming as shown in the example below:

with BASE;
package HIGHER_LEVEL is
  package NEW_BASE is new BASE(...);
  subtype T is NEW_BASE.T;

  function F(X  :  T) return T renames NEW_BASE.F;
  function G(X  :  T) return T renames NEW_BASE.G;
  ...
  function H(X  :  T) return T renames NEW_BASE.H;

  procedure P(X, Y :  in out T);
  ...
  procedure R(X :  T);
end;

The main disadvantage of this alternative approach is that it involves considerable rewriting and therefore suffers from the maintenance problems that are inherent in manual copying: any change in the specification of the operations of the type T would have to be repeated in the renaming declarations. Hence the renaming alternative is not very appealing.


NEXTPREVIOUSUPTOCINDEX
Address any questions or comments to adainfo@sw-eng.falls-church.va.us.