19.6. Encapsulation of Classes in Separate Modules

The base Modula-2 language provides for the creation of new ADTs using separate library modules with definition and implementation parts. Those ADTs may be object classes, and if so, the class has to be defined in the definition module, and then declared (with code) in the implementation, in the manner of any other type. The following rules need to be observed regarding compatibility between the two parts of the separate library module that contains such a class:

There is nothing startling in these rules. They are much the same as one would expect from the rules for declarations of procedures that have been defined in a definition module. In general, if one does the expected thing in this respect, all will be well.

One that may need comment is that if components are declared in the implementation (but were not defined in the definition part) then, even if they are revealed in the implementation module, they are only visible there, not in any client software--which can only look at the definition.

The following example illustrates these rules with a class that stores and can display a date. Obviously, the example is quite simple-minded, in that one would want, at the very least, to be able to do the display in a variety of formats, and only one is provided here.

DEFINITION MODULE Dates;
(* Simple class definition 
by R. Sutcliffe 1998 09 21 *)

TRACED CLASS Date;
  REVEAL SetDate, WriteDate;
  VAR
    year, month, day : CARDINAL;
    
  PROCEDURE SetDate (yr,mo,da : CARDINAL);
  PROCEDURE WriteDate;
END Date;

END Dates.

IMPLEMENTATION MODULE Dates;
(* Simple class implementation 
by R. Sutcliffe 1998 09 21 *)

FROM SWholeIO IMPORT
  WriteCard;
  
TRACED CLASS Date;
    (* reveals and attributes not repeated here *)
     
  PROCEDURE SetDate (yr,mo,da : CARDINAL);
  BEGIN
    year := yr;
    month := mo;
    day := da;
  END SetDate;
  
  PROCEDURE WriteDate;
  BEGIN
    WriteCard (year, 0);
    WriteCard (month, 0);
    WriteCard (day, 0);
  END WriteDate;
    
END Date;

END Dates.

This was tested with the simple application below. Observe again the necessity to CREATE the instance of the class before using it. Failure to do so will result in an empty class exception being raised.

MODULE TestDates;
(* to test class Dates
R. Sutcliffe 1998 09 21 *)

FROM Dates IMPORT
  Date;

VAR
  today : Date;
  
BEGIN
  CREATE (today);
  today.SetDate (1998, 12, 25);
  today.WriteDate;
END TestDates.

The result of running this was of course:

 1998 12 25

Observe that if the implementation needs to reveal additional attributes or methods it can do so, but this is of no consequence to the class interface in the definition and is entirely a local matter. Moreover, if additional class components are declared in the implementation, they may be revealed there as well.


Contents