If the reference NewClient is not nil in line 28 the object already exists. If we now simply create another object, the previous object will still be in memory but the name NewClient will no longer refer to it. So the previous object is now inaccessible to the program and it just remains there, taking up memory but being of no use to the program. This is sometimes referred to as memory leakage. (To prevent memory leakage we typically only create an object and assign it to a name when the name currently refers to nil.) If the name does not refer to nil, the event handler above displays a warning that an object already exists and then exits (lines 3031).
Conversely, before showing the objects data values (lines 5253) we make sure that the object actually exists (line 47), since referring to a non-existent object is an error.
procedure TfrmAccessObject.btnFreeClick(Sender: TObject) ;While this works, it is not necessary: the Free method already incorporates the test for nil, and only destroys the object if its reference is not nil. So, the program statement:
begin
if NewClient <> nil then
begin
NewClient.Free;
NewClient := nil;
end;
end;
ObjectName.Free;has the same effect as:
if ObjectName <> nil then ObjectName.Destroy;Notice the different connotations Free and Destroy have in Delphi. Because it tests for an object's existence, Freeing a non-existent object is safe. However, Destroying a non-existent object is not safe since Destroy does not first test for the object's existence. That is why we use the Free method rather than the Destroy method throughout this module.
There is also a further aspect to watch for. Notice that after the call to Free, we set the reference to nil. A call to Free should usually be followed immediately by setting the reference to nil:
ObjectName.Free;If we dont do this, but only free the object without setting it to nil, the program may later attempt to use this reference to an object that no longer exists a dangerous situation referred to as a dangling reference. To help protect against a dangling reference, Delphi provides the FreeAndNil procedure. We can replace these two lines with FreeAndNil (ObjectName) ; and get the same effect. Like Free, FreeAndNil is safe to use even if the object does not exist.
ObjectName := nil;
Memory leakage and dangling references are important potential sources of error in a program that can be very difficult to trace and so it is important to take care when creating and destroying objects. We return to this topic later in this chapter.
Example 4.2 Object constructors and destructors
In this and previous examples we have used the Create method but have not ever written a Create method in the classes we have defined. Similarly, we have Freed objects but not written any destructor. This is because we have used the Create constructor and the Destroy destructor (via Free) that are inherited from TObject. Often the inherited constructor and destructor are sufficient for our needs. However, sometimes we specifically write a constructor and/or a destructor: a constructor allows us to initialise the objects data fields to particular values as part of the object creation process, while a destructor allows us to do some forms of centralised housekeeping.Ex 4.2 step 1 Implementing a constructor and destructor
Modify the definition of the TClient class in ClientU.pas by adding a constructor (lines 9, 1924 below) and a destructor (lines 10, 2529).1 unit ClientU;
2 interface
3 type
4 TClient = class (TObject)
5 private
6 FAccNo: string;
7 FCName: string;
8 public
9 constructor Create (ACName, AnAccNo: string) ;
10 destructor Destroy; override;
11 function GetAccNo: string;
12 function GetCName: string;
13 procedure SetAccNo(const AnAccNo: string) ;
14 procedure SetCName(const ACName: string) ;
15 end;
16 implementation
17 uses Dialogs;
18 { TClient }
19 constructor TClient.Create(ACName, AnAccNo: string) ;
20 begin
21 inherited Create; // First create thru superclasss constructor
22 FAccNo := AnAccNo; // then initialise data field values
23 FCName := ACName;
24 end;
25 destructor TClient.Destroy;
26 begin
27 ShowMessage ('About to destroy client object') ; // 'tidy up'
28 inherited Destroy; // then destroy thru superclass's destructor
29 end;
30 { Methods GetAccNo, GetCName, SetAccNo and SetCName do not change }

