|
|
 |
 |
|
|
 |
 |
|
Join the Discussion
|
"Post your views and comments to this chapter of the free Delphi Programming Course"
Discuss!
|
|
 |
 |
|
|
 |
 |
 |
Now that you know the structure of a Delphi unit, and how Delphi helps you maintain a forms unit source, it's time to start creating your own collection of useful functions and procedures.
Depending on your background, creating and using code units can be easy to understand or may be confusing at first.
New ... unit
The simplest way to create a new unit for your project is to select File - New - Unit from the main Delphi IDE menu. The Code Editor will display the newly created unit and its skeleton code:
unit Unit2;
interface
implementation
end.
|
Naming (saving) a unit
The unit heading specifies the unit's name. It consists of the reserved word "unit", followed by a valid identifier, followed by a semicolon. Unit names must be unique within a project. To save a unit under a different name, go to File - Save As, in the Save As dialog box enter a valid file name and click ok.
Caution: If you change the name of the unit after, you'll need to change the source (uses list) of all the units that use this unit.
Note that the call to a procedure SomeProcedureName, defined in unit named MySuperUnit, consists of a unit name (MySuperUnit) followed by a period (.) and a procedure name. This fact is very important! If in some stage of the development of your project you decide to save MySuperUnit under a different name - you will need to change the call to any procedure inside that unit, since the name of the unit will no longer be MySuperUnit. This is the reason why you should give meaningful name to units in the early stage of unit "development".
Creating routines in units
I'll now quickly introduce the steps you need to do, in order to create a new routine (procedure or function) in a code unit.
To add a general purpose routine (procedure or function) to a code unit, do the following:
- Make sure the units source is displayed in the Code Editor
- Type the routine header in the interface section to make the procedure available to other units that will use this unit.
- Repeat the routine header in the implementation section and add the routine code
Here's an example:
unit Unit2;
interface
uses Dialogs, StrUtils;
procedure SayHelloTo(YourName : string);
implementation
procedure ReveredHello(YourName : string);
var hello : string;
begin
hello := YourName + ', hello!';
ShowMessage(hello);
end;
procedure SayHelloTo(YourName : string);
var hello : string;
begin
hello := YourName + ', hello!';
ShowMessage(hello);
ReveredHello(ReverseString(YourName));
end;
end.
|
Let's see what's "inside". We have two procedures: SayHelloTo and ReveredHello.
The SayHelloTo accepts a string parameter and displays a "hello" message (using the ShowMessage Delphi RTL function). This procedure calls the ReveredHello procedure. The header of the SayHelloTo is added to the interface section, making the procedure available to any unit using this unit. The header of the ReveredHello function is not added to the interface section, the function is "private" to this unit. What this means is that any unit using this unit will only be able to call the SayHelloTo, the ReveredHello is hidden to the "outside world"
The scope
Code units are not limited to functions and procedures. (The obvious fact, but I needed to write it down). A code unit can be used to define you own class (or type, whatever you prefer), or a component. Several routines in a code unit can share the same "set" of variables, constants, etc. If you define a variable (identifier) inside the interface section the variable will be "visible" to all units using this unit. If you define an identifier inside the implementation section, the identifier is hidden to the outer world.
When designing the overall structure of your application it is essential to have an understanding of the scope (visibility) of identifiers (routines, variables, types) defined inside the unit:
- Everything defined in the interface section will be available to all other units using this unit
- Everything defined in the implementation section is available only within the unit
Using standard (RTL) units
When you create your own units, you are responsible for listing the units your unit needs to use. You'll need to add different standard Delphi units, according to which routine you are implementing in your unit, to your uses list
In the above example, both procedures use the ShowMessage routine defined in the Dialogs unit. The SayHelloTo procedure uses the ReverseString procedure (StrUtils Delphi unit). This is why our uses clause (in the interface part) lists those two units (Dialogs, StrUtils).
Calling custom routines from form units
In order to let a form unit use the procedures defined in your own unit, you'll need to add the name of your unit to the uses list. Recall that you can place the uses list in the interface section and in the implementation section of a unit.
In general, add a reference to standard Delphi units in the interface section; add a reference to your own code units in the implementation section. Only when identifiers from another unit are used in the interface section is it necessary to list that unit in the interface uses clause.
This is how you would call the SayHelloTo (once again: Unit1 cannot call the ReversedHello function) procedure from the unit associated with our main form:
...
implementation
{$R *.dfm}
uses unit2; //don't miss this
procedure TForm1.Button1Click(Sender: TObject);
begin
Unit2.SayHelloTo('Zarko Gajic');
end;
...
|
And this is the "output":
As you can see two "hello" message boxes are displayed; the first one comes from the SayHelloTo procedure, another one comes immediately after displaying the reversed message.
Local, private, public?
As you can see, advantages of using code units include code reuse and information hiding. With the use of the appropriate inclusion statement (uses list), all identifiers listed in the interface portion of a unit are available to any program using the unit.
A code unit can contain constants, variables, user data types, routines, all of which can be hidden from the calling unit (defined in the implementation section). The calling unit needs only to know the interface syntax to utilize the public functionality contained within the unit - the inner workings of a unit file are for you to take care of.
We'll now move to the last part of this article to see what happens if unitA needs to use UnitB and UnitB needs to use UnitA.
More on scope, or "now you see me, now you don't!"
So, you've created your first code unit. Problems? One thing that might not be so obvious is how to know where to place the variable declaration in order to make a variable public, or private to a unit...
Let's start with an example. We'll add another unit to our sample project. Start by creating a new code unit (Unit3). Here's the code:
unit Unit3;
interface
uses Dialogs;
procedure ExposedRoutine;
var
Glob : string;
implementation
var
Privat : string;
procedure HiddenRoutine;
begin
ShowMessage('You do not see me!');
end; (*HiddenRoutine*)
procedure ExposedRoutine;
begin
ShowMessage('You see me!');
end; (*ExposedRoutine*)
end.
|
Confusing? If you try to access an identifier defined in this unit from unit1, this is what you'll see:
Bravo Delphi! When you write a unit name followed by a dot (.), Delphi will display a list of all identifiers defined in the interface section of a unit, which a calling unit can use/call.
That's it. You are now left on your own!
If you need any kind of help at this point, please post to the Delphi Programming Forum where all the questions are answered and beginners are treated as experts.
Some exercises for you...
Make a plan, create a simple Delphi project, try adding several code units, make your code as much reusable as you can...
To the next chapter: A Beginner's Guide to Delphi Programming
This is the end of the seventeenth chapter, in the next chapter, I'll show you how to ... ;)
First page > What is a Delphi unit? The structure of a unit. > Page 1, 2, 3
A Beginner's Guide to Delphi Programming: Next Chapter >> >>
Code navigation
|