Introducing (in this Chapter):
- Inheritance: deriving a new class from an existing one.
- Packaging a class in a unit.
- Overloaded methods & protected visibility.
- The Code Explorer and Project Browser.
- Layout of objects in memory.
In this chapter we continue our discussion on custom classes...
Ex 3.2 step 4 Benefits of encapsulation
This example illustrates that an object can store and manipulate data. If the data in the object is declared as private, as it is here, the only operations on the data that are possible are those made available through the public methods. So in OODriverU we can no longer use a statement like Inc(FCount) that we had in example 3.1 since it will give a fatal 'undeclared identifier' error for FCount. procedure TfrmCount.btnAddItemsClick(Sender: TObject) ;
begin
// Fatal, unknown identifier error
Inc(ItemCount.FCount) ;
end;
To achieve encapsulation, we declare the data in a class to be private. If we make the data public, it can be accessed from outside the object and the statement above will work, which completely negates the benefits of encapsulation.
TItem = class(TObject)
public
// WRONG! public data, so lose encapsulation
FCount: integer;
procedure AddItem;
function GetCount: integer;
procedure ZeroCount;
end;
Instead of the statement Inc(ItemCount.FCount) we send the AddItem message to the ItemCount object (line 31). Coding this separate class introduces a separation of concerns between the user interface and the application logic. The user interface now simply specifies what needs to be done, add an item, without being concerned about how to do it. The ItemCount object simply knows that when it receives an AddItem message, it must increment the value of FCount. It need know nothing about the event that gave rise to the AddItems message.
Ex 3.2 step 5 The Code Explorer
The Code Explorer displays a tree diagram showing the classes and methods defined in the unit displayed by the editor. It is docked to the left of the editor in versions up to Delphi 7. Use the menu sequence View | Code Explorer in Delphi 2006. If we expand the tree by clicking the plus signs at each node, the Code explorer gives a useful graphical view of the TItem class we have defined, showing the private data field, FCount, and the public methods, AddItem, GetCount and ZeroCount. The Code Explorer provides a quick way of navigating through a unit. By double-clicking on any of the final nodes in the trees, one goes directly to the code definition of that node.Example 3.2 Summary
There are three steps to the process of defining a class and creating an object:
- Define the classs structure and the implementation of the methods. (As a guide, we can imitate the way Delphi defines the form in a unit file.)
- Allocate a name (which acts as a reference) for an object of the class by listing it in the variable declaration of the unit that will use the object (and not in the unit defining the class as the RAD code does).
- Instruct Delphi to create the object and assign it to the name we declared so that we can use it in our program.
Example 3.3 Subclassing and Inheritance
Assume that we now need to enhance the program of example 3.2 to accommodate boxes of four items as well as just single items.Several options will work. We can have the btnAddBoxs OnClick event handler call AddItem four times:
procedure TfrmCount.btnBoxClick(Sender: TObject) ;
begin
// a poor approach!
ItemCount.AddItem;
ItemCount.AddItem;
ItemCount.AddItem;
ItemCount.AddItem;
end;
This, or something similar like a For loop, is not a good idea since we lose the separations of concerns the user interface must know that a box contains four items.
Another possibility is to add an AddBox method to the TItem class. This is a much better approach. A third alternative is to create a subclass of TItem containing an AddBox method. Both these alternatives maintain the separation of concerns criterion, while the third method also clarifies the distinction between an Item and a Box.


