The module Vectors in section 7.11 and the module Points in section 6.9 share some basic concepts in common. These two data types could be implemented as classes with the latter as the superclass as shown below.

DEFINITIONMODULEPointClassA;TRACEDCLASSPoints;REVEALassignR, firstCoord, secondCoord, abs, arg, assignP, reflectX, reflectY, reflect0, reflect45, scale, rotate, translate;TYPEPoint =ARRAY[1 .. 2]OFREAL;VARpoint : Point;PROCEDUREassignR (x, y :REAL);PROCEDUREfirstCoord () :REAL;PROCEDUREsecondCoord () :REAL;PROCEDUREabs () :REAL;PROCEDUREarg () :REAL;PROCEDUREassignP (abs, arg :REAL);PROCEDUREreflectX;PROCEDUREreflectY;PROCEDUREreflect0;PROCEDUREreflect45;PROCEDUREscale (scaleFactor :REAL);PROCEDURErotate (rotAngle :REAL);PROCEDUREtranslate (deltaX, deltaY :REAL);ENDPoints;ENDPointClassA.

A few names have been changed here to make them more generic for subclasses. The reader should compare this with the original and note the simplicity of the definition when the parameter of type Point can be left out because the procedure acts only on the variable point that is its attribute component. When moving from here to subclass Vectors, it seems appropriate to have a new type name, and to remove all functional duplicates. This results in an even simpler interface:

DEFINITIONMODULEVectorClassA;FROMPointClassAIMPORTPoints;TRACEDCLASSVectors;INHERITPoints;REVEALneg, add, sub, dotProduct;TYPEVector = Point;PROCEDUREneg;PROCEDUREadd (v : Vector);PROCEDUREsub (v : Vector);PROCEDUREdotProduct (v : Vector) :REAL;ENDVectors;ENDVectorClassA.

However, this design leaves something to be desired, because reflections and rotations, while relevant to points are not relevant to vectors. Moreover, while one might *scale* a point, it is thought of as a multiplication with respect to vectors. It is better design to come up with a base or superclass that has only the bare essentials that are common, and then derive both *Points* and *Vectors* from this. Such a more basic concept is the idea of an ordered pair, or more generally, of an ordered n-tuple. This base class can have in it only the facilities for working with such tuples, and let both *Points* and *Vectors* define their own components. Figure 19.2 illustrates the relationship among the classes:

Indeed, in the design of this suite of classes, the base class or first superclass is a generic module.

GENERICDEFINITIONMODULETupleClass (length :CARDINAL); (* base class for specific n-tuples R. Sutcliffe 1998 10 02 *)TRACEDCLASSTuples;REVEALassignCoord, fetchCoord, abs;CONSTlen = length; (* for inheritors *)VARcoords :ARRAY[1 .. len]OFREAL;PROCEDUREassignCoord (coordNum :CARDINAL; value :REAL);PROCEDUREfetchCoord (coordNum :CARDINAL) :REAL;PROCEDUREabs () :REAL;ENDTuples;ENDTupleClass.

To work with two dimensional vectors and points in a plane, this has to be refined by:

DEFINITIONMODULEOrderedPair = TupleClass (2); (* produce a 2-dimensional base class of tuples for corresponding vectors and points R. Sutcliffe 1998 09 28 *)ENDOrderedPair.

This in turn can be subclassed on the one hand to work with points in the plane.

DEFINITIONMODULEPoint2Class; (* subclasses OrderedPairs for the geometric notions of points R. Sutcliffe 1998 10 02 *)FROMOrderedPairIMPORTTuples;TRACEDCLASSPoints;INHERITTuples;REVEALreflectInAxis, reflect0, reflect45, scale, rotate, translate;PROCEDUREarg () :REAL;PROCEDUREreflectInAxis (n :CARDINAL);PROCEDUREreflect0;PROCEDUREreflect45;PROCEDUREscale (scaleFactor :REAL);PROCEDURErotate (rotAngle :REAL);PROCEDUREtranslate (deltaX, deltaY :REAL);ENDPoints;ENDPoint2Class.

On the other hand, it can be subclassed to work with two-dimensional vectors.

DEFINITIONMODULEVector2Class; (* subclasses OrderedPairs for vectors R. Sutcliffe 1998 10 01 *)FROMOrderedPairIMPORTTuples;TRACEDCLASSVector;INHERITTuples;REVEALabscissa, ordinate, neg, add, sub, dotProduct, arg;PROCEDUREabscissa () :REAL;PROCEDUREordinate () :REAL;PROCEDUREneg;PROCEDUREadd (v : Vector);PROCEDUREsub (v : Vector);PROCEDUREdotProduct (v : Vector) :REAL;PROCEDUREarg () :REAL;ENDVector;ENDVector2Class.

Observe that a method such as *Add* needs only to be passed the vector to add to SELF. In effect, such methods are messages to the object to add another vector to themselves. This is shown in some of the procedures of the partial implementation below.

IMPLEMENTATIONMODULEVector2Class; (* subclasses OrderedPairs for vectors R. Sutcliffe 1998 10 01 *)TRACEDCLASSVector;PROCEDUREabscissa () :REAL;BEGINRETURNcoords [1];ENDabscissa;PROCEDUREordinate () :REAL;BEGINRETURNcoords [2];ENDordinate;PROCEDUREneg;VARcount :CARDINAL;BEGINFORcount := 1TOlenDOcoords [count] := - coords [count];END;ENDneg;PROCEDUREadd (v : Vector);VARcount :CARDINAL;BEGINFORcount := 1TOlenDOcoords [count] := coords [count] + v.coords [count];END;ENDadd;PROCEDUREsub (v : Vector); (* similar to add *)ENDsub;PROCEDUREdotProduct (v : Vector) :REAL;VARcount :CARDINAL; sum :REAL;BEGINsum := 0.0;FORcount := 1TOlenDOsum := sum + coords [count] * v.coords [count];END;RETURNsum;ENDdotProduct;PROCEDUREarg () :REAL;BEGIN(* code to work out angle here. Specific to two-vectors. *)ENDarg;ENDVector;ENDVector2Class.

It should be evident to the reader that if complex numbers were not built in, they could be subclassed from ordered pairs as well, with new method components to handle such operations as multiplication and division.