Articles   Members Online:
-Article/Tip Search
-News Group Search over 21 Million news group articles.
Member Area
-Account Center
-Top 10 NEW!!
-Submit Article/Tip
-Forums Upgraded!!
-My Articles
-Edit Information
-Become a Member
-Why sign up!
-Chat Online!
-Indexes NEW!!
-Build your resume
-Find a job
-Post a job
-Resume Search
-Link to us
Visit Embarcadero
Embarcadero Community
Subclassing a versatile TList Turn on/off line numbers in source code. Switch to Orginial background IDE or DSP color Comment or reply to this aritlce/tip for discussion. Bookmark this article to my favorite article(s). Print this article
Delphi 2.x
User Rating
No Votes
# Votes
DSP, Administrator
Reference URL:
			Author: Max Kleiner

You can use a TList almost for everything, so an own class leads to better design 
and maintainability therefore the article shows how and why.


A certain view is that the TList class in Object Pascal (OP) is not a class from 
which we can descend, so the choice lies between subclassing (inheritance) or 
delegation (means create a separate class which holds the TList instance). But you 
can combine the two OO-technologies, especially you have multiple objects to store: 

Subclass the TList that exposes only function equivalents of TList 
Create a separate class that uses a TList instance 

Some Advantages and Tricks of TList: 

TList, which stores an dynamic array of pointers, is often used to maintain lists 
of objects or records. TList introduces properties and methods to 

Add or delete the objects in the list. 
Rearrange the objects in the list. 
Locate and access objects in the list. 
Sort the objects in the list. 

The Items of a TList are numbered from 0 to Count-1, that means zero based. Above 
D5 and Kylix, Borland changed the operation of TList with the introduction of a new 
descendant called TObjectList. They changed only the mechanism of freeing objects 
in a TList. 
If the OwnsObjects property of a TObjectList is set to True (the default), 
TObjectList controls the memory of its objects (by a new virtual method Notify), 
freeing an object when its index is reassigned or or when the TObjectList instance 
is itself destroyed, but the more items in the TList, the longer it takes. The 
worse is that a TList gets slower, so write always like in the following example 
your own Free-method (as it was with pre-Delphi 5 TList)! 

1   var
2     Childs: TSubTList;
4   for i := 0 to Childs.count - 1 do
5     BusinessClass(Childs[i]).Free;
6   Childs.Free

BusinessClass(Childs[i]).Free calls every object on the list and frees the memory 
of every object or record that we add on the list. 
Then Child.Free calls Destroy and then it calls Clear of TList but Clear only 
empties the Items array and set the Count to 0. Clear frees the memory used to 
store the Items array and sets the Capacity to 0. Be care about Delete, Delete does 
not free any memory associated with the item. 
Gain speed with TList 

The TList Sort mechanism is implemented with a quicksort algorithm, means we're 
fast enough, but how about the access? 
The normal way of accessing an object or item in a TList is the Items property in a 
default manner like theList[i]. The performance problem is the reading or writing, 
cause the compiler in OP inserts code to call getter or setter-methods, like 
theList.get[i] which checks the index between 0 and Count -1. If we want gain speed 
and get rid of the getter/setter we can call direct a variable of type PPointerList 
(named List), but no validation takes place. 


You then takes responsability of making sure reading or writing can't be beyond the 
ends of an array of the TList.   


The subclassing is like a wrapper class with simle one-line calls to the 
corresponding methods of the inherited TList without typecasts. The example shows 
how to add a record but with an object you have to change only the type and instead 
of Dispose use Free. 
The Method Add always inserts the Item pointer at the end of the Items array, even 
if the Items array contains nil pointers: 

7   var
8     Childs: TSubTList; //or TBrokerList
9     Childs.Add(BusinessClass.create(self));
11  //Not all of the entries in the Items array need to contain references to objects. 
12  Some of the entries may be nil pointers. to remove the nil pointers and reduce the 
13  size of the Items array to the number of objects, call the Pack method. 
15  type
16    TBrokerRec = record
17      intVal: integer;
18      strVal: string;
19      ptrStr: pChar;
20    end;
21    PBrok = ^TBrokerRec;
23    TBrokerList = class(TList)
24    protected
25      procedure freeElement(elem: PBrok);
26      function GetItems(Index: Integer): PBrok;
27      procedure SetItems(Index: Integer; item: PBrok);
28    public
29      destructor destroy; override;
30      function Add(Item: PBrok): Integer;
31      procedure Delete(index: integer);
32      function First: PBrok;
33      function indexOf(item: PBrok): Integer;
34      procedure Insert(index: integer; item: PBrok);
35      function Last: PBrok;
36      procedure pClear;
37      function Remove(item: PBrok): Integer;
38      property Items[Index: Integer]: PBrok read GetItems write SetItems;
39    end;
41  TBrokerList
43  destructor TBrokerList.destroy;
44  begin
45    clear;
46    inherited Destroy;
47  end;
49  function TBrokerList.Add(Item: PBrok): Integer;
50  begin
51    result := inherited Add(Item);
52  end;
54  procedure TBrokerList.Delete(index: integer);
55  begin
56    freeElement(items[index]);
57    inherited delete(index);
58  end;
60  function TBrokerList.First: PBrok;
61  begin
62    result := inherited First;
63  end;
65  procedure TBrokerList.freeElement(elem: PBrok);
66  begin
67    if elem <> nil then
68      dispose(elem);
69  end;
71  function TBrokerList.indexOf(item: PBrok): Integer;
72  begin
73    result := inherited indexOf(item);
74  end;
76  procedure TBrokerList.Insert(index: integer; item: PBrok);
77  begin
78    inherited insert(index, item);
79  end;
81  function TBrokerList.Last: PBrok;
82  begin
83    result := inherited Last;
84  end;
86  procedure TBrokerList.pClear; //instead of Free from outer class
87  var
88    x: Integer;
89  begin
90    for x := 0 to count - 1 do
91      freeElement(items[x]);
92    inherited clear;
93  end;
95  function TBrokerList.Remove(item: PBrok): Integer;
96  begin
97    result := indexOf(item);
98    if Result <> -1 then
99      delete(result);
100 end;
102 function TBrokerList.GetItems(Index: Integer): PBrok;
103 begin
104   result := inherited get(index);
105 end;
107 procedure TBrokerList.SetItems(Index: Integer; item: PBrok);
108 begin
109   inherited put(index, item);
110 end;

Vote: How useful do you find this Article/Tip?
Bad Excellent
1 2 3 4 5 6 7 8 9 10


Share this page
Download from Google

Copyright © Mendozi Enterprises LLC