home *** CD-ROM | disk | FTP | other *** search
-
-
-
- Chapter 16
- 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 VIRTUAL1.PAS
- of virtual functions. We must state that ================
- this program does not contain a virtual
- function, 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 16-1
-
- Virtual Methods
-
- NOW TO MAKE IT A VIRTUAL METHOD
- ____________________________________________________________
-
- Examine the example program named ================
- VIRTUAL2.PAS, and you will find only one VIRTUAL2.PAS
- small change in the 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
-
- Page 16-2
-
- Virtual Methods
-
- they must all be capable of being called by the same method
- call.
-
-
-
- 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.
-
-
-
-
-
-
- Page 16-3
-
- Virtual Methods
-
- VIRTUALS AND POINTERS
- ____________________________________________________________
-
- The example program named VIRTUAL3.PAS is ================
- nearly identical to the last program except VIRTUAL3.PAS
- that this 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 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 PERSON.PAS
- definition 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 previously defined object
-
- Page 16-4
-
- Virtual Methods
-
- named Person. You will notice that each of ================
- the objects have a method named Display which SUPERVSR.PAS
- 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.
-
-
-
- A COMPLETE EMPLOYEE PROGRAM
- ____________________________________________________________
-
- Although the program named EMPLOYEE.PAS is a ================
- very short program that does very little, it EMPLOYEE.PAS
- is a 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
-
- Page 16-5
-
- Virtual Methods
-
- 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 EXERCISE
- ____________________________________________________________
-
- 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 16-6