home *** CD-ROM | disk | FTP | other *** search
-
-
-
- Chapter 14
- ENCAPSULATION & INHERITANCE
-
-
- Encapsulation is the cornerstone upon which object oriented
- programming is built, and without which it would not exist. We
- will cover the topic of encapsulation in this chapter in enough
- depth to illustrate its use and what it can do for you in software
- development. Because there are many new terms in this chapter, you
- could very easily become intimidated, and wish to simply give up
- on this new topic. You can be assured that the time spent studying
- encapsulation will be greatly rewarded as you apply this new
- technique in your software development efforts.
-
- Object oriented programming is not a panacea to solve all of your
- software problems, but it is a new and improved way of programming.
- In fact it is really more of a software packaging technology than
- a new method of programming. You will find that your software will
- be easier to write and debug as you gain experience using this new
- packaging method. Like any new endeavor however, it will require
- some effort on your part to master these concepts.
-
- If you are using an older version of TURBO Pascal you will not be
- able to compile and execute the example programs in this chapter.
- Versions 5.5 and newer can be used, and as mentioned earlier, it
- would be worth your effort to upgrade to a newer version so you can
- learn these techniques to improve the quality of your programs.
-
-
- OUR FIRST ENCAPSULATION
- _________________________________________________________________
-
- The example program named ENCAP1.PAS contains our ==============
- first example of encapsulation. In order to keep ENCAP1.PAS
- it easy to understand, it was kept very short. ==============
- This results in a program that does not illustrate
- the advantage of using object oriented
- programming, but it does give us a start in the right direction.
- With this in mind, load ENCAP1.PAS and we will study the code
- contained in it.
-
- Line 5 has our first new reserved word, object. This is used in
- much the same way that the reserved word record is used, but it has
- a much different meaning. An object is permitted to have not only
- data embedded within it, but also procedures, functions, and
- constructors. Constructors will be described in detail later.
- Since data plus procedures and functions can be grouped together
- in this fashion, the object is said to be encapsulated. An object
- is therefore a group of related data and the subprograms that
- operate on that data, all entities being very closely coupled
- together.
-
-
-
- page 14-1
-
- Chapter 14 - Encapsulation and Inheritance
-
- WHAT IS A METHOD?
- _________________________________________________________________
-
- A method is a term used with object oriented programming, and for
- the time being we will simply say that a method is either a
- function or a procedure (including a constructor). A method is
- therefore a method for doing an operation on some data. Lines 8
- through 10 are method headers and give the pattern for all calls
- to these methods which can be used by the compiler to check for the
- correct number and types of parameters.
-
- Once again, we promise to discuss the constructor soon. For the
- time being, simply think of it as another procedure.
-
- The entire object type definition is given in lines 5 through 11.
- This object contains two variables named length and width, each of
- type integer, and three methods which can be used to operate on the
- two variables. In the same manner that the definition of a type
- in Pascal does not actually give you a variable to use, only a
- pattern, the definition of an object type does not give you an
- object. We will declare the objects when we get to line 30 of this
- program.
-
- You will note that we are already using new terminology, but this
- is necessary. The field of object oriented programming has its own
- vocabulary and in order for you to understand technical articles
- in this field, you must begin now to learn the new terminology.
- It won't be too long until you feel somewhat comfortable with it.
-
-
- THE METHOD IMPLEMENTATION
- _________________________________________________________________
-
- The object type definition describes in detail what we can do with
- the object but we must now describe what actions will take place
- when each of the methods is called. The implementation for each
- method will define the operations for that method and are defined
- in lines 13 through 28 of this example program. The only thing
- that is really different about these methods is the way their
- headers are defined, namely the inclusion, in the header, of the
- object type name Box dotted to the method name. This is required,
- but we will wait until the next example program to define why it
- is needed.
-
- The observant student will also notice that we are referring to the
- object variables within the methods of that object without the
- object name dotted to the variable name. This is because the
- implied object name is automatically "with"ed to the variable names
- within the method implementations, allowing the variables to be
- directly referred to within the objects because of the definition
- of object oriented programming. It should be obvious that any
- mathematics or logical operations can be done within the
- implementations of the methods. In fact, you can perform any legal
- Pascal operations within the methods, just like you can in any
-
- page 14-2
-
- Chapter 14 - Encapsulation and Inheritance
-
- Pascal function or procedure. Very short operations were selected
- here because we wish to illustrate the interfaces to the methods
- at this point in the tutorial.
-
-
- AN INSTANCE OF AN OBJECT
- _________________________________________________________________
-
- We need another new term at this point. When we use the object
- type to declare variables of that type as we do in line 30, we are
- creating instances of that object type. An instance is like a
- variable in conventional Pascal (non object oriented), except that
- it can do more and has some very interesting properties that a
- simple variable does not have. In line 30 we have created three
- instances of the object type named Box and each has two simple
- variables associated with it. Three methods are available which
- can be called to operate on these variables. We therefore have
- three objects named Small, Medium, and Large. In order to
- initialize the values stored within the objects we call the three
- objects in lines 34 through 36 to store values in their internal
- variables by dotting the name of the object to the name of the
- method we wish to call. You will note that this looks like the
- same technique we use to refer to the fields of a record. We
- display the area of the three boxes in lines 38 through 40 using
- the same technique used to initialize the values stored, and the
- program is complete.
-
- We seem to have accomplished very little with this program that we
- could not have more easily accomplished with an even shorter
- standard Pascal program, and that is true. This program is only
- meant to introduce some of the mechanics of object oriented
- programming. Additional programs will be used to illustrate some
- of the uses of this new technique.
-
-
-
- NEW TERMINOLOGY
- _________________________________________________________________
-
- You may note that we switched terminology halfway through the above
- paragraphs. We began by referring to the object types as object
- types and calling the variables declared in line 30 instances.
- Later we began calling the instances objects. In this tutorial we
- will refer to the types as object types and the variables either
- as objects or instances. This terminology is consistent with
- current practice and should help you learn the new terminology.
-
- Another very important point is the fact that we pass a message to
- a method rather than call a subprogram as in conventional Pascal.
- The difference is rather subtle, but there really is a difference
- as we will see a little later in this tutorial.
-
-
-
-
- page 14-3
-
- Chapter 14 - Encapsulation and Inheritance
-
- WHAT DID WE ACCOMPLISH?
- _________________________________________________________________
-
- In this program we defined an object type, then declared several
- instances of that type, one of which was named Small. The object
- named Small has two internal variables that should only be accessed
- via its methods, so we will refer to them as private data points.
- Actually, they should be unavailable to any user outside of the
- method implementations but Borland chose not to make them private
- in version 5.5. It is up to you to discipline yourself to not
- refer to them directly. (TURBO Pascal version 6.0 has a way to
- make the data private. We will study this in the next example
- program.) The proper way to use the object is to send a message
- to the object telling it to do something to itself. In the case
- of the Init method, we are telling it to store the two values in
- its private variables named length and width, and in the case of
- the Get_Area method, we are telling it to give us the product of
- its own internally stored width and length which we can then print
- out.
-
- Remember that in the beginning of this chapter we said that object
- oriented programming is a code packaging technique. That should
- help to explain some of the strange things we did in this program.
- As we continue through the example programs, we will see that
- everything here was done for a reason and you will eventually learn
- to use and prefer object oriented programming methods over the old
- familiar procedural programming method you have been using.
-
- Be sure to compile and execute this program to see if it does what
- the comments say it will do.
-
-
- DATA & CODE PROTECTION
- _________________________________________________________________
-
- The data and methods are protected from outside influence because
- they are packaged together within an object. Of even more
- importance is the fact that because they were to be packaged
- together, they were probably carefully planned and designed
- together during the design stage. This would probably result in
- a more understandable program. The object keeps the data and
- methods together and keeps them working in close synchronization.
-
- An object type is sometimes referred to as an abstract data type
- in the technical literature discussing object oriented programming.
-
-
- MORE ENCAPSULATION
- _________________________________________________________________
-
- The example program named ENCAP2.PAS uses most of the same
- techniques as the last program but this is much more meaningful
- since it illustrates one of the simplest advantages of using object
- oriented programming.
-
- page 14-4
-
- Chapter 14 - Encapsulation and Inheritance
-
-
- In this program, we define two object types in ==============
- lines 5 through 21, Box and Pole. Each has its ENCAP2.PAS
- own unique kinds of variables associated with it, ==============
- and each has three methods that can be used with
- these kinds of data. The method definitions in lines 35 and 46
- clearly illustrate why the object name must be associated with the
- method name in the method implementation. This allows you to use
- the same method name in more than one object definition. In
- addition to the two method definitions named Set_Data given here,
- we could also define and use another procedure with the name
- Set_Data that was a normal Pascal procedure just like any others
- we have used in prior chapters of this tutorial. Using the same
- method name in several places is often referred to as name
- overloading in object oriented programming terminology.
-
- You will note that in lines 5 through 21 we define the object types
- which define what each object will do. In lines 23 through 55 we
- define the method implementations which define how we do it. It
- is assumed that you know enough Pascal at this point to understand
- what each method does, so nothing more will be said about the
- details of this program except for the private types.
-
-
-
- THE PRIVATE TYPE
- _________________________________________________________________
-
- Borland added the private type to version 6.0, but it is not as
- flexible as it could be. You will notice that the order of
- declarations within the objects is significantly different in this
- program. Within an object declaration, you are permitted to have
- public variables and methods and private variables and methods, but
- you are required to list all public entities first. The reserved
- word private is then used with all private entities following its
- use. Within each section, the variables must come first, followed
- by the methods.
-
- Even though the variables are listed as private in these classes,
- they are still available to the main program because they are in
- the same Pascal unit. If the objects were placed in a different
- unit as discussed in chapter 13, the variables defined as private
- would be unavailable in the calling program. If you are using
- TURBO Pascal 5.5, you will have to remove the word private and
- rearrange the variables to put them ahead of the methods in the two
- object definitions.
-
- In lines 57 and 58, we declare several objects of the defined
- object types and use some of them in the main program. We can
- finally illustrate one of the biggest advantages of object oriented
- programming.
-
- We should all agree that it would be silly and meaningless to
- multiply the height of one of the poles by the width of a box. If
-
- page 14-5
-
- Chapter 14 - Encapsulation and Inheritance
-
- we were using standard procedural programming with all variables
- defined globally, it would be a simple matter to accidentally write
- height*width and print out the result thinking we had a meaningful
- answer. By encapsulating the data within the objects, we would
- have to really work at it to get that meaningless answer because
- the system itself would prevent us from accidentally using the
- wrong data. This is true only if we have agreed not to use any of
- the data directly but to do all data access through the available
- methods.
-
- Encapsulation is a form of information hiding, but TURBO Pascal has
- a rather weak form of it because, as mentioned earlier, Borland
- chose not to make the variables within the object private in
- version 5.5. In TURBO Pascal 6.0 the variables can be defined as
- private variables as mentioned earlier, and are therefore
- unaccessible outside of the unit in which they are declared. The
- client would be forced to use only the methods provided by the
- author of the object to access the contained data. This is true
- information hiding and adds some degree of protection to the
- internal data.
-
- If you are using TURBO Pascal 5.5, it is up to you to never refer
- to the data within the object directly as stated by Borland in the
- OOP Guide included with the compiler. Even if you are using
- version 6.0, you must still discipline yourself to not refer to the
- private data within the defining unit.
-
- The careful student will notice that since all data is carefully
- tied up within the objects, inadvertent mixing of the wrong data
- is impossible provided a few simple rules are followed as discussed
- above. Once again, this is such a small program that it is
- difficult to see the advantage of going to all of this trouble.
- In a larger program, once the objects are completed, it is a simple
- matter to use them knowing that they are debugged and working.
-
- After the data are all printed out, some of the variables are
- changed in lines 80 through 82, and the same output statements are
- used to reprint the same data so you can observe the changes.
-
-
-
- A FEW RULES ARE NEEDED
- _________________________________________________________________
-
- As with any new topic, there are a few rules we must follow to use
- this new technique. The public variables must all be declared
- first in the object followed by the public method definitions. The
- reserved word private is then declared followed by the private
- variables and finally the private methods. The names of all
- variables within an object must be unique and may not be repeated
- as the names of any of the formal variables in any of the methods.
- Thus length, width, len, and wid must be unique as used in lines
- 6, 7, 10, and 11. The names of formal variables may be reused in
- other methods however, as illustrated in lines 6 and 7, and all
-
- page 14-6
-
- Chapter 14 - Encapsulation and Inheritance
-
- names may be reused in another object. It should be obvious that
- all object type names must be unique within a given file and all
- objects must have unique names.
-
- All of the above rules are obvious if you spend a little time
- thinking about them. They should therefore not be a stumbling
- block to anyone with some procedural programming experience.
-
-
- WHAT IS A CONSTRUCTOR?
- _________________________________________________________________
-
- It is time to keep our promise and define just what a constructor
- is. In this present context, that of simple objects, the
- constructor does very little for us, but we will include one for
- nearly every object to illustrate its use. The constructor can be
- named anything desired but it would be best to stick with the
- convention and name every constructor Init as suggested by Borland.
- The constructor is used to initialize all values within an object
- and do any other setup that must be done to use an object. The
- constructor should be called once for every declared object. When
- we get to the topic of virtual functions, constructors will be
- absolutely required for every object, but for the simple objects
- we are using here, they are optional.
-
- It would be best to include a constructor in every object type,
- define the constructor to initialize all variables within the
- object, and call the constructor once for each instance of the
- object type. Until we get to virtual methods, none of this is
- required, but it would be good practice to get in the habit of
- doing it.
-
-
- WHAT IS A DESTRUCTOR?
- _________________________________________________________________
-
- A destructor is another method that can be used for cleanup when
- you are finished with an object. It is usually used in conjunction
- with dynamic allocation to assure that all dynamically allocated
- fields associated with the object are deallocated prior to leaving
- the scope of the object. A destructor is not illustrated in this
- tutorial but it should be easy for you to define and use one when
- you have a need for one.
-
-
-
- OUR FIRST INHERITANCE
- _________________________________________________________________
-
- Load the example program named INHERIT1.PAS for ==============
- our first example of a program with inheritance. INHERIT1.PAS
- As always, our first encounter with this new topic ==============
- will be very simple.
-
-
- page 14-7
-
- Chapter 14 - Encapsulation and Inheritance
-
- In lines 7 through 14 we define a simple object type defining a
- vehicle and a few characteristics about the vehicle. We have the
- ability to store a few values and read them out in several ways.
- Of course, most of the interest is in the interfaces, so the
- implementations are purposely kept very small.
-
- In lines 17 through 35, we declare two additional object types that
- use the Vehicle type as a base for the new types as indicated by
- the previously defined name Vehicle in parentheses in the object
- definitions in lines 17 and 26. The Vehicle object type is said
- to be the ancestor type and the two new object types are called
- descendant types. The descendant types inherit some information
- from the ancestor types according to well defined rules. The
- variables in the ancestor type are all included within the
- descendant types and are available in objects of the descendant
- types just as if they had been defined within the descendant types.
- For that reason, all variable names must be unique within the
- ancestor type and within each of the descendant types. A name can
- be reused in one or more descendants however, as is illustrated in
- lines 18 and 27 where the variable name Passenger_Load is used in
- both object types.
-
- The method names from the ancestor object types can be repeated in
- the descendant object types but this has the effect of overriding
- the method of the same name in the ancestor making the ancestor
- method unavailable for use in objects of the descendant types.
- Objects instantiated of the type Car therefore, have the three
- methods available in lines 11 through 13 of the ancestor type, the
- constructor in line 19 which overrides the constructor in line 10
- of the ancestor type, and the function given in line 22. This
- object therefore has five different methods to perform its required
- operations.
-
- Objects of type Truck have five methods available also, the two in
- lines 11 and 12 and the one in line 33. The two in lines 29 and
- 34 of the descendant overrides the two in lines 10 and 13 of the
- ancestor object type.
-
- You should note that even though some of the methods were
- overridden in the descendant object type, they do not affect the
- ancestor, and instances of the Vehicle type have two variables and
- four methods available.
-
- In effect we have an object hierarchy which can be extended to as
- many levels as necessary to complete the task at hand. The most
- important part of object oriented programming is the definition of
- the objects in a meaningful manner, but it is not something you
- will learn to do overnight. It will take a great deal of practice
- until you can see the objects in any given project in such a way
- that a clear solution can be found. I was somewhat intimidated by
- the clever examples found in a classic text on object oriented
- programming until I talked to a man that had shared an office with
- the author at the time he was writing that particular book. I
- learned that what was finally put in the book was at least the
-
- page 14-8
-
- Chapter 14 - Encapsulation and Inheritance
-
- fourth iteration of each problem and in some cases the seventh
- before he finally arrived at a good solution. We will have more
- to say about this topic as we progress through this tutorial.
-
-
- HOW DO WE USE THE OBJECTS?
- _________________________________________________________________
-
- The implementations of the methods are given in lines 39 through
- 92 and should be self explanatory, except for a few notable
- exceptions. You will note that in line 81 we send a message to the
- Vehicle.Init method to initialize some data. A change to the
- Vehicle type will be reflected in the Truck type also because of
- this call. In lines 64 and 65 we are using some inherited
- variables just as if they had been defined as part of the
- descendant object types.
-
- In lines 96 through 98 we instantiate one of each and send a
- message to their constructors in lines 102 through 104 then print
- out a few of the stored values.
-
- Lines 113 through 116 are repeated in lines 120 through 123 where
- they are placed within a with section to illustrate that the with
- can be used for the calls to the methods in the same manner that
- it is used for accessing the fields of a record. Any other details
- of this program can be gleaned by the diligent student. Be sure
- to compile and execute this program so you can verify the given
- result.
-
-
- WHY USE INHERITANCE?
- _________________________________________________________________
-
- Once you have an object that is completely debugged and working,
- it is possible that it can be reused on your next project. If you
- cannot use it exactly as is, but are required to make a change to
- it, you have two choices. You can modify the existing code and
- hope you don't introduce any analysis or coding errors, or you can
- inherit it into a new object and add code around the completely
- debugged object without actually modifying the original code.
- Several studies have shown that modifying existing code lead to a
- high probability of introducing errors into the modified code that
- are difficult to find because you are not as familiar with the code
- as you should be. Adding a few methods to an existing object,
- however, is not nearly as error prone and is the preferred method.
-
-
-
- AN OBJECT IN A UNIT
- _________________________________________________________________
-
- Load the example program named VEHICLES.PAS for an example of the
- proper way to package the object so it can be conveniently reused
- for another project.
-
- page 14-9
-
- Chapter 14 - Encapsulation and Inheritance
-
-
- The object type definition is given in the public ==============
- part of the unit so it is available to any Pascal VEHICLES.PAS
- program which needs to use it. The implementation ==============
- of the methods are hidden in the implementation
- part of the unit where they are not directly available to any
- calling program. Note that it is also possible to define a few
- local methods within the implementation for use only within the
- implementation but none are illustrated here. There is no body to
- this unit, only the end statement in line 39 so there is no
- initialization code to be executed during loading. It would be
- perfectly legal to include an initialization body, but even if you
- do, you should be sure to include a constructor to be called once
- for each object. This is to prepare you for the use of virtual
- functions which we will study in the next chapter.
-
- Referring back to the discussion of the second example program in
- this chapter, you will find the means necessary to make the
- variables truly private in this program. If you move the two
- variables to a location just after the end of the methods, and add
- the reserved word private just before the two variables, they will
- be truly private and unavailable for direct modification outside
- of this unit. If you are using TURBO Pascal 6.0, you should make
- this modification and try to access the variables directly in the
- calling program which will be discussed next.
- You must compile this unit to disk so it can be used with the rest
- of the example programs in this chapter.
-
-
-
- ANOTHER OBJECT IN A UNIT
- _________________________________________________________________
-
- The example program named CARTRUCK.PAS continues ================
- the new packaging scheme by including two CARTRUCK.PAS
- descendant object types in its interface after ================
- telling the system that it uses the Vehicles unit
- in line 6.
-
- The remainder of this unit is constructed just like the last one
- so nothing more needs to be said about it. Be sure to compile this
- unit to disk so it will be available for use with the next example
- program.
-
- Note that this unit could have been further divided into two
- separate units, one for each object type, but it was felt that it
- was important to illustrate that several can be combined in this
- manner if desired. In like manner, the last unit could have been
- combined with this unit, but once again, it was desired to
- illustrate the generality of program decomposition and packaging.
-
-
-
-
-
- page 14-10
-
- Chapter 14 - Encapsulation and Inheritance
-
- USING THE OBJECTS DEFINED IN UNITS
- _________________________________________________________________
-
- Load the program named INHERIT2.PAS for a program ================
- that uses the units of the last two example INHERIT2.PAS
- programs and is identical to the program named ================
- INHERIT1.PAS.
-
- The only difference in these two programs is in the way the code
- was packaged. The second way is much more general and more
- conducive to good software engineering practices because it allows
- separate development of each of the three program units. Each can
- be refined independently of the other two and the overall package
- can be simpler to debug and maintain. It should be clear that any
- changes to the Car object, for example, will be localized to that
- single unit and not scattered all over the software terrain.
-
-
- AN ARRAY AND A POINTER
- _________________________________________________________________
-
- Examine the example program named INHERIT3.PAS ================
- for an example of the use of a pointer to an INHERIT3.PAS
- object and the use of an array of objects. ================
-
- This program is nearly identical to INHERIT2.PAS
- except for the addition of an array of Car type objects named
- Sedan[1] to Sedan[3], and the definition of a pointer to the Truck
- type object named Semi_Point. Lines 16 and 17 illustrate the
- initialization of the array of Sedan, and lines 23 through 26
- illustrates its use when the data is printed out. An object is
- dynamically allocated in line 18 and it is then initialized in the
- next line. Its use is illustrated in lines 28 through 40 and it
- is deallocated in line 41.
-
- TURBO Pascal 5.5 and newer, have an extension to the New procedure
- allowing the dynamic allocation and the initialization to take
- place in the same procedure call. The line;
-
- New(Semi_Point, Init(1, 25000.0, 18, 5000.0));
-
- can be used to replace lines 18 and 19 in this program if you
- desire to do so.
-
- This program should illustrate that objects can be used with arrays
- and pointers in the same manner as a record. Be sure to compile
- and execute this program.
-
-
- WHAT IS MULTIPLE INHERITANCE?
- _________________________________________________________________
-
- Multiple inheritance allows the programmer to inherit data and
- methods from two or more ancestor objects. When this is done
-
- page 14-11
-
- Chapter 14 - Encapsulation and Inheritance
-
- however, there is a real problem if there are two variables or
- methods of the same name and it is up to the programmer to somehow
- define which will be used by the descendent. Some object oriented
- programming languages allow multiple inheritance, but most do not.
- TURBO Pascal has no provision for multiple inheritance, and Borland
- has made no indication at this time whether future versions will
- permit it.
-
-
- WHAT SHOULD YOU DO NOW?
- _________________________________________________________________
-
- You have reached a major point in your excursion of object oriented
- programming, because you now have most of the knowledge you need
- to do some serious object oriented programming. The best thing for
- you to do at this point is stop studying and get busy programming,
- using some of these techniques for your projects. The only topic
- left is the use of virtual methods and you can easily defer its use
- for a long time.
-
- One point should be made before you begin a serious programming
- project. Your first program could have too many objects and be
- nearly unreadable unless you strive to use only a few objects.
- After you gain experience, you can confidently use more objects
- with each programming project. For your first project, define only
- a few objects and write the majority of the program in standard
- procedural programming methods. Add a few more objects to your
- next project and, as you gain experience, you will feel very
- comfortable with the use of objects and your programming methods
- will be very clear.
-
- Now is the time to begin using this new knowledge but be sure you
- enter the water slowly the first time.
-
-
- PROGRAMMING EXERCISES
- _________________________________________________________________
-
- 1. Modify ENCAP2.PAS in such a way to multiply the height of the
- short pole times the length of the medium box and print the
- result out. Even though this is possible to do, it requires
- you to expend a bit of effort to accomplish. Remember that
- you should not use the components of an object directly, only
- through use of the available methods.
-
- 2. Add an object named Pick_Up to INHERIT2.PAS of type Truck and
- initialize it to some reasonable values. Print out its
- loading and efficiency in a manner similar to the Semi.
-
-
-
-
-
-
-
- page 14-12