             INTRODUCTION TO OBJECT-ORIENTED PROGRAMMING.
             

 It is good programming practice to develop sub-routines, procedures or
 functions for blocks of code which perform well-defined and frequently
 repeated tasks. The procedure or function may have 'formal' parameters,
 as declared, so that it can be called with different 'actual' parameters.

 It is also sensible to bundle together any associated data such as name,
 address and telephone number, into a record. Each of the associated items
 of data is stored in a separate 'field' of the record and can be accessed
 using the syntax <Record Name>.<Field Name>,  e.g. Personnel.Name

 Even though these techniques are employed, it is still possible to use a
 procedure or function with the wrong data. In many circumstances it is
 therefore wise to lock together procedures and functions with the
 associated data. This is object-oriented programming or object-oriented
 design (OOD) of programs.

 Object-oriented programming was introduced in the early 70's in the
 simulation language Simula and then developed in the Smalltalk language.
 Object-oriented design of software has only recently entered the mainstream
 of computing.  Turbo Pascal, version 5.5, with Object-Oriented Programming
 (OOP), was introduced in 1989.

 Object-oriented programming was based on the observation that computer
 programs perform actions on objects, such as records in databases, lines of
 text, and graphical shapes.  Traditional software was simply a list of
 actions performed on certain data in a certain sequence.  Changing the data
 or the actions usually meant changing the program, sometimes significantly,
 and hence disturbing tested code.  OOP offers an opportunity to change the
 way the data is manipulated by extending the program rather than changing
 it, so that tested code is retained.

 An 'object' type is an extension of the structured 'record' type. However,
 it also contains functions and procedures, declared locally within the
 object type declaration, and these are used to manipulate the data.
 These functions and procedures are jointly called 'methods'. Although the
 method and its parameters are declared within the object type declaration,
 the code for the implementation of the method is defined outside the object,
 somewhere in the program before that particular method is called.

 Since the method is declared within the object type declaration, the method
 is rigidly bound to that object type. This is called Encapsulation.

 As with records, the type is first declared in the 'type' declaration part
 of the program. Then specific variables of that type are declared in the
 'var' declaration part of the program.

 This can be illustrated by means of a simple example, which compares the
 conventional way to initialize a record with the initialization of the
 same data by means of an object defined with its own method.  The two
 programs are called RECINIT.PAS and OBJINIT.PAS respectively. The type
 declaration for the object is as follows:

     type
        Obj = object            { compared with 'Rec = record' }
          i : integer;
          r : real;
          s : string[50];
          procedure Init( int : integer; re : real; st : string);
             { this last line is not in the record type declaration }
        end;

 The essential difference is that the procedure 'Init' is declared after
 the data fields in the object declaration.  This Init procedure has ceased
 to exist as a separate entity and is now an integral part of the 'Obj'
 object type, although the code for the initialization method is defined
 separately and referenced by means of the 'dot' notation as below:

     procedure Obj.Init( int : integer; re : real; st : string);

       { In the record case, the procedure name would just be 'Init',
         but the parameters would include the formal 'var DataRec : Rec' }

     begin
       i := int;
       r := re;
       s := st;
     end;

 The program is completed by a 'var' declaration and a main part as follows:

     var
       ThisObj  : Obj;

     begin
       ClrScr;
       ThisObj.Init(1234, 9.876, 'This is the string entry for this object');

          { In the record case, a final actual parameter, a rec-type
            variable 'ThisRec' would be included }

       writeln( 'The integer value is ', ThisObj.i);
       writeln( 'The real value is ', ThisObj.r);
       writeln( 'The string is " ', ThisObj.s, '"');
     end.

 If more than one variable of type 'obj' is declared, each variable would
 have its own region of memory reserved for the field entries, but would
 share a common pointer to the procedure 'Init'.  Furthermore, it would be
 impossible to call this procedure without specifically involving an object
 of type 'obj'.

 The procedure is now referred to by the dot notation as 'Obj.Init', which
 tells the compiler that the procedure is part of the 'Obj' object type.
 When a variable, or instance, 'ThisObj', of the type 'Obj' is declared,
 the same dot notation is used  -  ThisObj.Init(....);

 Another difference is the absence of the last parameter in the procedure.
 The formal parameter 'var DataRec : Rec' is not replaced with a parameter
 referring to the object, since the data fields are already bound to the
 procedure by the object type declaration.

 In OOP parlance, a 'class' or 'object type' is an abstraction that provides
 a template for objects, which are called 'instances' of that class.
 Thus 'Obj' is a template (type or class) and 'ThisObj' is an instance.

 Whereas in literary work plagiarism is unacceptable, it is positively
 encouraged in OOD. Objects are inherited and extended and in many cases
 there is a natural hierarchy as with graphical objects:

          location(x,y)
          point   (x,y,visible)
          circle  (x,y,visible,r)
          arc     (x,y,visible,r,start angle,end angle)

 The data fields for location can be inherited and then extended for the
 point by the addition of a boolean (visible) field. A circle then inherits
 these fields and adds the radius field and so on. It is the field structure
 of the object type, not actual numeric values, that is inherited. Each
 instance of each object type must be initialized, so that specific
 numerical values are assigned to each data field.

 A descendant object type inherits type compatibility with all its ancestor
 types. This relaxation of Turbo Pascals normal type compatibili`ty rules is
 explained in more detail in the note COMPAT.TXT which may be consulted
 later when use is made of this fact.

 Methods to move a point from (x1,y1) to (x2,y2) can be inherited by a
 circle and an arc, although the methods to show and hide the different
 graphical objects will be different.

 One of the major advantages of object-oriented programming is the ability
 to build a hierarchy of descendant objects, with each descendant inheriting
 access to all its ancestors' code and data fields. 'Inheritance' is a major
 attraction of OOD, but some care has to taken when inherited methods are
 not relevant to the descendant object as for example for a point 'show'
 and a circle 'show':

 procedure Point.Show;
 begin
   Visible := True;             {boolean field is set 'true' for information}
   PutPixel(X, Y, GetColor);    {pixel at X,Y is 'put' in foreground colour}
 end;

 procedure Circle.Show;
 begin
   Visible := True;              {boolean field for information & inspection}
   Graph.Circle(X, Y, Radius);   {draw circle in current foreground colour}
 end;

 In this case the inherited method 'Show' from the object type point must be
 overridden for the object type circle. This is achieved by using 'Virtual
 Methods', which is explained in detail in the note VIRTUAL.TXT which should
 be read next.


 OOPINTRO.TXT
 revised 31.5.93

