


                                                       Chapter 15
                                                  VIRTUAL METHODS



Since we covered encapsulation and inheritance in the last chapter,
we are left with only virtual methods to complete the major topics
of object oriented programming.  Virtual methods, as they are
called in TURBO Pascal, have several other names in the literature
to describe the same technique.  This technique is sometimes called
run-time binding or late binding referring to when the decision is
made as to what method will respond to the message.  The use of
virtual methods moves the responsibility of selection from the
client (the logic sending the message) to the supplier (the methods
responding to the message).  We will begin with a skeleton of a
program without a virtual method and add one to show the effect of
adding a virtual method.



WITHOUT A VIRTUAL METHOD
_________________________________________________________________

The example program named VIRTUAL1.PAS will be     ==============
used as the starting point for the study of         VIRTUAL1.PAS
virtual methods.  We must state that this program  ==============
does not contain a virtual method, it is only the
starting point for studying them.

The objects included here are very similar to the objects
describing vehicles which we were working with in the last chapter. 
You will notice that all three objects contain a method named
Message in lines 11, 20, and 31.  The Message method will be the
center of our study in the first three example programs.  It should
be pointed out that the constructors for the three objects are
called in lines 98 through 100 even though a constructor call is
still not absolutely necessary in this case.  We will have more to
say about the constructor calls during the next example program.

Compile and execute the program and you will find that even though
it is legal to pass the objects of type Car and Truck to the method
named Output_A_Message in lines 109 and 110, the method that is
called from line 86 is the method named Message in the parent type
Vehicle.  This is probably no surprise to you since we defined an
object of type Vehicle as a formal parameter of the method
Output_A_Message.  We need only one small change and we will have
a virtual procedure call.

Even though this program seems to do very little, it will be the
basis of our study of virtual methods so you should study the code
in detail.



                                                        Page 15-1

                                     Chapter 15 - Virtual Methods

NOW TO MAKE IT A VIRTUAL METHOD
_________________________________________________________________

Examine the example program named VIRTUAL2.PAS,  ================
and you will find only one small change in the     VIRTUAL2.PAS
code but a world of difference in the way it     ================
executes.

The careful student will notice the addition of the reserved word
virtual in lines 13, 22, and 33.  This makes the method named
Message a virtual method which operates a little differently from
the way it did in the last program.  Once again, we call the three
constructors in lines 100 through 102 and this time the constructor
calls are absolutely essential.  We will discuss why in a couple
of paragraphs.

Once again we send a message to Output_A_Message three times in
lines 110 through 112 and line 88 is used to send a message to the
Message method.  When we compile and execute this program, we find
that even though the method Output_A_Message only uses the parent
type Vehicle, the system calls the correct procedure based on the
type of the actual object passed to this method.  The system sends
a message to the objects of the correct type instead of to the
parent type as may be expected.  It should be clear to you that the
object that is to receive the message is not known at compile time
but must be selected at run time when the object arrives at the
method Output_A_Message.  This is known as late binding since the
type is not known until run time as opposed to early binding where
the type is known at compile time.  Every subprogram call in this
entire tutorial, up to this point, has been early binding.

You will note that even though the method Output_A_Message only
knows about the objects of type Vehicle, it has the ability to pass
through other types, provided of course that they are descendant
types of Vehicle.  The method Output_A_Message only passes the
message through, it does not do the selection.  The selection is
done by the objects themselves which answer the messages passed to
them.  This means that the sender does not know where the message
will be answered from, and it is up to the receiver to find that
a message is being sent its way and to respond to it.  It is often
said that the supplier (the method doing the work) must make the
decision to answer the message, rather than the client (the user
of the work done).  The burden is placed on the supplier to do the
right thing.

If a method is declared virtual, all methods of that name must also
be virtual including all ancestors and all descendants.  It is not
possible to declare part of the methods of the same name virtual
and part standard.  All parameter lists for all virtual methods of
the same name must also be identical since they must all be capable
of being called by the same method call.




                                                        Page 15-2

                                     Chapter 15 - Virtual Methods

ASSIGNING DESCENDANTS TO ANCESTORS?
_________________________________________________________________

It is legal in any object oriented language to assign a descendant
object to an ancestor variable but the reverse is not true.  A
vehicle, for example, can be used to define a car, a truck, a bus,
or any number of other kinds of vehicles so it can be assigned any
of those values.  A car on the other hand, is too specific to be
used for the definition of anything but a car, so it cannot have
any other value assigned to it.  A vehicle is very general and can
cover a wide range of values, but a car is very specific and can
therefore only define a car.


WHY USE A CONSTRUCTOR?
_________________________________________________________________

The constructor is absolutely required in this case because of the
way the authors of TURBO Pascal defined the use of virtual
functions.  The constructor sets up a pointer to a virtual method
table (VMT) which is used to find the virtual methods.  If there
is no pointer, the system jumps off to some unknown location and
tries to execute whatever happens to be there and could do almost
anything at that unknown and undefined point in the code.  So it
is important to call a constructor once for each object as is done
here so the pointer to the VMT can be initialized to the proper
value.  If you make several objects of one type, it is not enough
to call a constructor for one object and copy that object into each
of the other objects.  Each object must have its own constructor
call in order to prevent a system crash.

The strange looking code in line 6 tells the system to check each
call to a virtual function to see if the constructor has been
called.  This slows the program down slightly but will result in
an error message if a virtual method is called prior to its VMT
being properly set up with a constructor call.  After a program is
thoroughly tested, the code can be removed from line 6 to speed up
the program slightly by eliminating the checks.  Be warned however,
that a call to a virtual method without A VMT will probably result
in the computer hanging up.


VIRTUALS AND POINTERS
_________________________________________________________________

The example program named VIRTUAL3.PAS is nearly   ==============
identical to the last program except that this      VIRTUAL3.PAS
program uses pointers to objects instead of using  ==============
the objects directly.

You will notice that once again, the methods named Message are all
defined as virtual and a pointer type is defined for each object
type.  In lines 99 through 101, three pointers are declared and
memory is dynamically allocated on the heap for the objects

                                                        Page 15-3

                                     Chapter 15 - Virtual Methods
themselves.  The objects are all sent a constructor message to
initialize the stored data within the objects and to set up the VMT
for each.  The rest of the program is nearly identical to the last
program except that Dispose procedures are called for each of the
dynamically allocated objects.  The code used in line 6 of the last
program to force a check of each virtual method call has been
removed to illustrate that it doesn't have to be there if you are
sure a message is sent to a constructor once for each object with
a virtual method.

Compiling and executing this program will give the same result as
the last program indicating that it is perfectly legal to use
pointers to objects as well as the objects themselves.


AN ANCESTOR OBJECT
_________________________________________________________________

The example program PERSON.PAS is not a complete   ==============
program at all but only an object definition         PERSON.PAS
within a unit.  This unit should pose no problem   ==============
for you to understand so we will not say much
except to point out that the method named Display
is a virtual method.

This example program, as well as the next two example programs,
have been carefully selected to illustrate the proper way to
package objects for use in a clear understandable manner.

Compile this unit to disk in order to make it available for use in
the remainder of this chapter.


SOME DESCENDENT OBJECTS
_________________________________________________________________

The example program named SUPERVSR.PAS is another  ==============
unit which contains three descendants of the        SUPERVSR.PAS
previously defined object named Person_ID.  You    ==============
will notice that each of the objects have a method
named Display which is virtual just as the same
method in the ancestor object was.

The interface for each object has been purposely kept very simple
in order to illustrate the use of objects.  The implementation has
also been kept as simple as possible for the same reason so the
diligent student should have no trouble in understanding this unit
completely.

Once again, be sure to compile this unit to disk in order to make
it available for use in the next few example programs. 





                                                        Page 15-4

                                     Chapter 15 - Virtual Methods

A COMPLETE EMPLOYEE PROGRAM
_________________________________________________________________

Although the program named EMPLOYEE.PAS is a very  ==============
short program that does very little, it is a        EMPLOYEE.PAS
complete program to handle a very small amount of  ==============
data about your employees.

You will notice that we declare an array of ten pointers to the
Person_ID object and one pointer to each of the three descendant
objects.  In the main program we send a message to the constructor
for each of the array elements.  Inspection of the Person_ID.Init
code will reveal that this initialization does nothing.  It is used
to initialize the pointer to the VMT for each object, so the
message must be sent.  We then dynamically allocate six objects of
assorted descendant objects being careful to send a message to the
constructor for each object.  This is done to generate a VMT for
each object as it is allocated.  Finally, we send a message to the
first six objects pointed to by the array of pointers instructing
them to display their values.

When the program is compiled and executed, we find that the virtual
methods were called as explained in the last example program.  Even
though only one kind of pointer was passed to the Display method,
three different messages were actually displayed, each message
being of the proper kind based on the type of pointer used.

You will notice how clean and neat the main program is.  It is
extremely easy to follow because all of the implementation details
have been moved to the objects themselves.  Once the objects are
carefully defined and debugged, the main program is usually a snap
to write and debug.

Object oriented programming requires a whole new mindset over the
procedural methods you have been using but after you catch on to
the technique, you will find your programs much easier to debug and
maintain.  The one thing you should avoid is the use of too many
objects in your first program.  It is best to define a few simple
objects for your first attempt at object oriented programming and
write the rest of the program using standard procedural methods. 
Then as you gain experience, you can begin using more and more
objects until you finally write a program that is essentially all
objects.  Of course, you will find that you will always write at
least part of your program in a standard procedural format as was
done in EMPLOYEE.PAS in this chapter.

PROGRAMMING EXERCISES
_________________________________________________________________

1.   Add a new object type to SUPERVSR.PAS to define a Consultant
     defining appropriate data fields for him, then add a couple
     of Consultant type objects to EMPLOYEE.PAS to use the new
     object type.


                                                        Page 15-5
