home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 2
/
ctrom_ii_b.zip
/
ctrom_ii_b
/
PROGRAM
/
PASCAL
/
OOPTUT34
/
OOPINTRO.TXT
< prev
next >
Wrap
Text File
|
1993-06-12
|
8KB
|
172 lines
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