Association and Composition - Delphi OOP Part 9 - Chapter 21

106 19
Materials written by John Barrow. Modifications by Zarko Gajic
Back to Chapter 20

Example 9.3 Deep copies and the Assign method

As a final example in this part, we?ll look at Delphi?s convention for making deep copies. Making shallow copies is easy: we simply declare a reference of the appropriate type and then assign this to the object being copied through an assignment statement. To facilitate making deep copies, Delphi provides the virtual method Assign in the TPersistent class (which is derived directly from TObject).

Assign is a more sophisticated version of our CopyFrom method and we?ll modify our previous example to use it.
unit CustomerU;interfaceuses Classes;    type    TCustomer = class(TPersistent)    private      FPhoneNo: string;      FName: string;    public      property Name: string read FName write FName;      property PhoneNo: string read FPhoneNo write FPhoneNo;      procedure Assign (aCustomer: TPersistent) ; override;    end;implementation{ TCustomer }procedure TCustomer.Assign(aCustomer: TPersistent) ; begin    if aCustomer is TCustomer then    begin      Name := TCustomer(aCustomer).Name;      PhoneNo := TCustomer(aCustomer).PhoneNo;    end    else      inherited Assign (aCustomer) ; end;end. Before we look at the details of the Assign method, test it by entering this version and then changing TSale to use Assign. This means substituting Assign for CopyFrom in TSale?s Create method (ie ex 9.2 step 3 becomes FCustomer.Assign (ACustomer) ;).
If we compare this code with the previous version of TCustomer (ex 9.2 step 2) we see a number of changes.

TCustomer is now derived from TPersistent rather than TObject.

TPersistent is defined in unit Classes and so we include that in the Uses clause. Instead of procedure CopyFrom we now have procedure Assign, with a parameter of type TPersistent and not of TCustomer. This overrides the virtual Assign procedure in TPersistent and so we declare it with the override keyword.

The CopyFrom method had two program statements. But Assign has quite a bit of additional code that makes it much more general than CopyFrom, so we?ll go through this method line by line. First we see that the source parameter, aCustomer, is now of type TPersistent.

This allows polymorphism and gives Assign the potential to accept classes other than its own class, TCustomer, if they are derived from TPersistent. We assign the appropriate values should the incoming parameter be a TCustomer. Since the aCustomer parameter is declared as a TPersistent, we perform the necessary typecasting before they can assign the values. Should we want Assign to accept other TPersistent-derived classes in addition to TCustomer, we add further else if statements for each additional class.

Finally, if the type of the parameter does not match any of the types catered for in the else if clauses, we invoke the inherited Assign method.

The inherited Assign is called only when the destination object cannot perform the deep copy, ie if the else ifs do not cater for the incoming parameter type. In this case Assign in TPersistent calls the AssignTo method of the source object. The AssignTo method swaps around the order of the source and destination classes to cater for the possibility that the source object can perform the deep copy. If it can, all is well. If not, it raises an exception and the deep copy has failed.

AssignTo is not needed in this case since for this example the source and destination classes are always the same, ie always TCustomers. However, for interest?s sake, we include the AssignTo method below to illustrate the principle involved. (AssignTo is declared as Protected in TPersistent.)

procedure TCustomer.AssignTo(aCustomer: TPersistent) ; begin   if aCustomer is TCustomer then   begin     TCustomer(aCustomer).Name := Name;     TCustomer(aCustomer).PhoneNo := PhoneNo;   end   else     // will raise an exception     inherited AssignTo (aCustomer) ; end; We can test the AssignTo method by commenting out lines and so force Assign to fail. The program still works as before without changing TSale because TPersistent?s Assign automatically calls TCustomer?s AssignTo to perform the required copying. (You can verify this by placing a breakpoint on the first statement in Assign and then single stepping through the code until you have executed the AssignTo.) In passing, in these two methods we have the inherited keyword as part of an Else statement, so invoking the superclass?s method only under certain conditions.
Let's sum this chapter, ..., on th next page...
Source...
Subscribe to our newsletter
Sign up here to get the latest news, updates and special offers delivered directly to your inbox.
You can unsubscribe at any time

Leave A Reply

Your email address will not be published.