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.