1. Computing & Technology

Discuss in my forum

Association and Composition - Delphi OOP Part 9 - Chapter 20

By , About.com Guide

Materials written by John Barrow. Modifications by Zarko Gajic

Back to Chapter 19

Association, composition and immutability

Because TSale is immutable (introduced in the previous chapter), neither its data field nor the link between TSale and TCustomer can be changed. However, TCustomer itself is not immutable and so the values of TCustomer can be changed via the link between the user interface and ThisCustomer. When ThisSale accesses ThisCustomer, it will read the changed values set by the user interface.

We need to go back to the requirements of the application to decide if this is what is wanted or not. Assuming that the amount of a sale should always be immutable, we have three possibilities for the customer details:

  1. First we could say that once a customer has been created those details must be immutable. If a customer has a change of telephone number or name, that customer object must be destroyed and a new customer must be created. To implement this approach we need to make TCustomer immutable by changing its properties to be readonly.
  2. Alternatively, when a customer’s details change, we might want to change the existing TCustomer object and have these changes reflected immediately in the associated TSale object. This is the situation in example 9.1. It may be the situation that a company’s credit control department would require so that they always have the most recent customer details attached to any sale.
  3. Finally, when a customer’s details change, we might want to make these changes in the existing TCustomer object but not reflect these changes in the TSale object. Instead, the TSale object must retain the TCustomer values that were valid at the time the sale was made. (Maybe the legal department would require this situation.) This involves composition instead of association, and is the approach we explore in example 9.2.

Example 9.2 Composition

In composition, the composed object has complete, unshared ownership of the constituent object. This means that no-one beside the composed object can access it. To have this control, the composed object must itself create the constituent object, and not simply assign a reference to an existing object (as with association). To change example 9.1 from association to composition we must change TSale’s Create method. Instead of simply assigning a reference to the incoming TCustomer object (example 9.1, step 2, line 21) it must create a separate, private :TCustomer object that has the same data values as the incoming object. In other words, instead of the shallow copy we used above, we need to create a deep copy of ThisCustomer. (A shallow copy is where we create an additional reference to an existing object. A deep copy is where we create a second object initialised to the same data values as the first.)

Ex 9.2 step 1 Creating a deep copy

To make a deep copy, we modify TSale’s Create (example 9.1, step 2) to create a new object and to initialise this new object’s data fields to those of the incoming object:
 constructor TSale.Create(ACustomer: TCustomer; AnAmount: string) ;
 begin
   inherited Create;
   // making a deep copy
   FCustomer := TCustomer.Create;
   // .. copying the data fields
   FCustomer.Name := ACustomer.Name;
   FCustomer.PhoneNo := ACustomer.PhoneNo;
   FAmount := AnAmount;
 end; 
This creates a completely independent copy of the ACustomer data that is accessible only to the TSale object through its private FCustomer data field.

To test this version, run it and enter the Customer and Sale details. Check that the Display Sale box is displaying the correct values. Now change the Customer details, click Customer and then Display Sale. Unlike example 9.1, the Display Sale box’s details now do not change. Only if you first click on the Create Sale button, thus destroying the previous TSale object and creating a new one with new values for the Customer, will the Display Sale box’s details change. So the TSale instance has its own copy of these values and is independent of the original TCustomer instance. This change is also contained entirely within the TSale object: neither TCustomer nor TfrmCompAssoc, the user interface, are aware of this change.

By introducing the deep copy, instead of the shallow copy used in example 9.1, we have taken a first and very important step in moving from association to composition.

©2012 About.com. All rights reserved.

A part of The New York Times Company.