UNITS IN TURBO PASCAL
When Nicklaus Wirth originally defined Pascal, it was intended to be a very small language to be used primarily for teaching programming concepts to computer neophytes. A program would be contained in a single file and compiled in its entirety each time it was compiled. There was no provision for splitting a program up into smaller parts, compiling each part separately, and linking all of the parts together into a final completed package.
Since human beings make mistakes, and because the entire program must be recompiled each time any mistake is discovered, pure Pascal is unsuitable for very large programs. Seeing this problem, many compiler writers have defined some method by which a large program could be broken down into smaller parts and separately compiled.
This chapter will define and illustrate the way Borland International has chosen to allow TURBO Pascal to be broken up into smaller pieces to permit compilation of smaller portions of a program. This allows you to write a much larger program since it does not have to be compiled all at once.
PART OF A PROGRAM
Example program ------> AREAS.PAS
Load the program named AREAS.PAS and display it on your monitor. This is the first example of a TURBO Pascal unit and although it is similar to a program in many ways, it has a few differences which must be pointed out. We will start by pointing out the major sections, then get into the details of each section.
You will first notice that this program begins with the reserved word unit instead of our usual program, followed by the unit name, Areas. In line 10, the reserved word interface is used and all of the statements following it down to the next reserved word implementation, are part of the interface with any program outside of this unit. The reserved word, implementation, defines the beginning of the definitions and executable parts of the private portion of the unit.
Finally, in lines 48 through 50, we find what appears to be a program block just like we have been using all through this tutorial, but actually is not. We will see in a few paragraphs that this is the initialization section and does a very specific job for us even though somewhat different than what we have become used to.
THE INTERFACE PART
Following the unit name we have a section of code in lines 10 through 14 that define the interface of this module to the outside world. Anything defined here is available to the outside world and can be used by any other program provided it has a "uses Areas;" statement in it. Constants, types, and variables could also be defined here, and if they were, they too would be available to any user program, but in this case, only the four functions are made available. It should be fairly obvious that the functions calculate the areas of four different geometric shapes.
These four functions are available for use in any program in much the same way that any of the standard Pascal functions are available for use. The only difference is that a uses clause must be included in the calling program in order to use these functions.
THE IMPLEMENTATION PART
From line 16 through line 47 we have the implementation part as delineated by the reserved word implementation and the beginning of the initialization block. The implementation part is the actual workhorse of the unit since it contains all of the executable code for the four functions defined above.
Lines 26 through 31 contain the code needed to generate the area of a circle, and this code is no different than the code that would be used if this function were placed in the declaration part of any Pascal program. There is a difference in the function header since the formal parameters are not repeated here, but are defined only in the interface part in this example. TURBO Pascal allows you to either drop the formal parameters here or include them if you think the code would be more readable. If you include them, they must be exactly as shown in the interface part or you will get a compile error.
A LOCAL PROCEDURE
In lines 20 through 24, we have a procedure that is used within one of the four functions, namely the first. It is really a stupid procedure since it really wastes time setting up linkage for the procedure call and does nothing that couldn't be done just as easy with a simple multiply, but it does illustrate that you can use another procedure within the unit body. The procedure Mult_Two_Numbers cannot be used outside of this unit because it is not included in the interface part of the unit. It is, in effect, invisible to the outside world.
The variable My_Pi would be more correctly represented as a constant but it is defined as a variable to illustrate the use of the body of the unit later. Since My_Pi is not defined in the interface part of the unit, it also is invisible to the outside world and in fact protected from accidental corruption by a misplaced statement in another program. The procedure Mult_Two_Numbers and the variable My_Pi for all practical purposes have an impenetrable barrier around them protecting them from unauthorized use or modification by the outside world, but the functions internal to this unit have free access to them just as in any other program.
WHAT IS THE BODY USED FOR?
Lines 48 through 50 constitute the body of the unit and although they appear to consist of another executable program that can be called and used, they actually perform another very specific and useful purpose. This is an initialization section and all of the statements in this part of the unit are executed once and only once, and they are executed when the main program is loaded. This is done automatically for you by the system. There is no way provided for you to call the statements in the body after the program has begun execution. This is why the variable My_Pi was defined as a variable, so we could use this section to initialize it to a useful value as an illustration.
The body can have function and procedure calls that are executed when the program is loaded, as well as loops or conditional statements.
If you would like to execute some statements during initialization and again during the execution of the program one or more times, you can write a procedure or function to accomplish your desires and call it at the appropriate times in the main program.
SELECTIVE NAMING OF FUNCTIONS AND PROCEDURES
If you will study the interface part of this unit you will find that everything you need to use this unit is contained within it, provided that you know enough about plane geometry to understand the functions. You should strive for this understanding in all of your interfaces so that the implementation doesn't even require consultation. Keep in mind, that if you need to, you can include comments to further define the functions in the interface part of the unit.
At this time, you should compile this unit. You will have to compile it to disk rather than only to memory so it will be available for use later in this chapter. You do this by using the menus to change the Compile/Destination to the Disk option. Note that it will not generate an .EXE file but instead a .TPU file. This is Borland's filename extension for a unit.
Example program ------> PERIMS.PAS
Load the file named PERIMS.PAS for another example of a unit. This is similar to the last except that it does not contain an internal procedure, and it is composed of three procedures that calculate the perimeters of geometric shapes, all of which are visible to the outside world because they are included in the interface part of the unit. Once again, we have a private variable named My_Pi and a block of code (actually a single statement) to initialize the value of My_Pi when the unit is loaded.
Be sure you compile this unit to disk in the same manner as the last and they will be ready for use. Note that it is not a requirement that a unit be composed of only functions or only procedures. They can be freely mixed in a unit. It was only done this way in this example because it was convenient.
Now that we have several functions and procedures that can be used to calculate the areas or perimeters of several different shapes, we need a program to illustrate their use, so if you load and display the program named GARDEN.PAS you will have an example of their use.
HOW DO WE USE OUR DEFINED UNITS?
Example program ------> GARDEN.PAS
GARDEN.PAS is a very simple program that uses one of the functions and one of the procedures. The only thing you must do is add the names of the units prior to using the external functions or procedures. Lines 16 and 17 each use one of our newly defined routines. As you can see, there is nothing magic about the new routines, and once you include the unit names in a uses statement, the new routines are in a sense, an extension to the Pascal language. Compile and run this program and see that it really does what you expect it to do.
ONE MORE EXAMPLE OF UNIT USE
Example program ------> SHAPES.PAS
Load and display the program named SHAPES.PAS for another example of using a predefined unit. In line 3, this program includes our new unit named Areas so all four of the area functions are available, and in fact, all four are used within the body of the program. This program should not be difficult for you to understand and you will be left to study it on your own. The supplied unit named Crt is also included in the uses clause to allow the use of the keyboard subprograms in lines 15 and 16.
MULTIPLE USES OF AN IDENTIFIER
Suppose we wanted to move the variable named My_Pi to the interface section in both of the units we defined earlier. Then in the program named GARDEN.PAS when we included both of the units in the uses statement, both variables named My_Pi would be available for use so we would have a bit of a problem defining which one we really meant to use. TURBO Pascal has a way to tell the system which one you wish to use by using a qualifier in much the same way that you use a field of a record. The variable name Areas.My_Pi would refer to that variable from the unit named Areas, and the name Perims.My_Pi would refer to the variable from the unit named Perims.
You could even define a new variable of the same name in your main program and refer to it by the qualified name Garden.My_Pi if you chose to. This is not recommended as it would get very confusing to you. The compiler would be very happy to compile and run such a program, because it would not get confused.
It is not illustrated in the example program, but this technique applies to procedure and function names as well. If you used the same procedure name in two different units, you could specify which procedure you intend to use by using the dot notation with the unit name and the procedure name. Unit_Name.Procedure_Name would therefore refer to the procedure named Procedure_Name that is a part of the unit named Unit_Name.
WHY USE UNITS?
There are basically three reasons to use units in your programming. First, some programs are so large that they should be broken up into smaller chunks for ease of handling and reasonable compilation size.
Secondly, once you complete the code to perform a certain job, you may wish to use the same code in another program to do the same job. If you put the code in a unit, it is ready to simply call and use again in the same manner that we reused Areas in SHAPES.PAS. This is becoming a rather important topic in software engineering usually referred to as "Reusable Software".
THIS IS INFORMATION HIDING
Finally, it is sometimes important to hide a portion of code from the rest of the program to assure that it cannot be unduly modified by an error somewhere else in the program. This too is becoming an important area of software engineering and is usually referred to as information hiding.
Advance to Chapter 14
Return to the Table of Contents