Procedural abstraction

\oopindex{procedural abstraction} In the specification of the abstract data type stack given above, the behavior of the stack has been characterized by means of equational axioms. We distinguish two ways to construct a stack, namely by using the constructor function new and by applying the function push. In addition to these constructors the operations empty, top and pop are specified. A different way of characterizing the behavior of a stack is by a matrix relating the meaning of the various operations to the constructors. \begin{center} \mbox{}\hspace{-2.5cm} \begin{tabular}{| r | c c |} \hline & new & push(x,s') \\ \cline{1-3} empty(s) & true & false \\ top(s) & error & x \\ pop(s) & error & s' \\ \hline \end{tabular} \end{center}\ln We have omitted the preconditions for the operations top and pop, and instead defined the result as error. \nop{ The different way to implement an abstract data type may be distinguished according to how the matrix describing the abstract type is partitioned. See  [Cook90]. } Traditional ways of implementing abstract data types favor a horizontal partitioning of the matrix. This results in defining the operations on a concrete representation of the type by means of a case-statement distinguishing between the possible constructors of the type. In contrast, the object oriented approach to implementing the abstract data types may be regarded as a vertical partitioning of the matrix. In this approach, the operations are grouped around the constructors. This method is referred to in  [Cook90] as procedural abstraction, since the operations defined for the constructors provide a procedural interface to the abstract type comprising these constructors. The differences between these approaches come to light when extending an abstract type with either a constructor or operation. Adding a constructor to a traditional abstract data type implementation requires to extend the definition of each operation with an additional case defining the result of the operation for the new constructor. In practice this means a modification of the source code. Using procedural abstraction, as in the object oriented approach, allows to add a new constructor incrementally. One merely has to add the new constructor defining the results of each operation. When adding a new operation to an abstract data type implementation, it depends on the implementation language whether access to the source code is needed to add the operation (which must define the result for each possible constructor). In the object oriented approach, adding a new operation requires the use of inheritance, to create a variant that inherits the functionality of the original constructor while adding the new operation. \nop{ For a discussion of the tradeoffs, see  [Cook90]. }