Сергей Григорьев дата публикации 18-02-2003 13:05 Удобная оперативность. Класс TObjectList
Цель статьи поделиться с народом опытом и премами работы с классом
TObjectList, который появился еще в пятой версии, но так видимо нигде широко освещен и не был.
TList - папа для TObjectList |
C Delphi я шесть лет, пришел с DOS-овского ассемблера, и по крайней мере для меня
всегда крайне остро стояла проблема организовать удобоваримое хранение
даже не каких - то абстрактных данных , а вполне определенных логических структур, ну проще
говоря тех же классов. Класс TList хранит список указателей, поэтому особого удобства
ощутить не получается. Класс TObjectList главным образом отличается тем, что определяет список объектов TObject, а не указателей.
Когда-то, разрабатывая собственную систему электронных таблиц, я в полной мере насладился
VCL-ным новшеством.
Итак, класс TList.
- Родители:
- TObject;
- Назначение:
- Список указателей на память;
- Применение:
- Динамическое хранение указателей на объекты;
- Функциональность:
- Позволяет добавлять и удалять объекты в списке, обеспечивает порядок в списке, имеет навигацию по списку и сортировку;
- Недостатки:
- Неудобно оперировать хранимыми данными, требует особого внимания за памятью;
Класс TObjectList.
- Родители:
- TObject -> TList;
- Назначение:
- Контейнер объектов типа TObject;
- Применение:
- Динамическое хранение объектов;
- Функциональность:
- Позволяет добавлять и удалять объекты в списке, обеспечивает порядок в списке, имеет навигацию по списку и сортировку. Также имеет собственный контроль за памятью;
- Недостатки:
- По крайней мере, в данной области я ничего лучше не знаю;
- Достоинства:
- Смотри недостатки у папы наоборот;
Начнем с того, что имеется еще два сходных класса TComponentList и TClassList в принципе они идентичны с
TObjectList разница я думаю понятна (кому не понятно , я думаю не составит особых проблем выяснить это из Helpа).
Руководствуясь этим, под TObjectList я подразумеваю и два других.
У TObjectList есть свойство OwnsObjects, которое управляет механизмом контроля за памятью. Истина - все ОК !!!
Ложь - теряем нервы. По умолчанию свойcтво имеет True, и я не вижу особой необходимости вмешиваться.
Сразу оговорюсь код проверен в шестерке, но в пятом , я думаю проблем не будет. Ну давайте представим, что где-то в дебрях нашей системы необходимо динамически на этапе выполнения генерировать какие-нибудь DataSetы, а
конкретно допустим обычный TQuery, и хранить их в памяти при этом имея возможность легко обращаться к любому
из них (на месте TQuery естественно может оказаться любой ваш класс например такой как TMyClass).Примеров
можно придумать достаточно много - тема крайне актуальна !
Sorry исходников не размещал. Ну оно и понятно - тема очень абстрактна. Да и все достаточно тривиально,
я думаю, что по представленным листингам не сложно будет понять суть.
Листинг 1.
ExClass = class(TObject)
private
ExObjList:TObjectList;
public
function GetDataSet(Name:TComponentName):TQuery;
procedure NewDataSet(SQL:String;Name:TComponentName);
end;
| |
На листинге 1 код нашего класса - примера, который содержит объект класса TObjectList
по ходу выполнения приложения пользователь (как некий пример) имеет возможность выполнять различные
запросы к базе и при этом результат каждого из них хранить в памяти, естественно имея возможность модифицировать
данные. Т.е. получаем набор DataSet ов, количество которых нам неизвестно. Когда пользователь выполняет
новый запрос вызываем метод NewDataSet с указанием SQL параметра и имени по которому будем идентифицировать
в дальнейшем Query.
Метод NewDataSet реализован следующим образом:
Листинг 2.
procedure TExClass.NewDataSet(SQL: String;Name:TComponentName);
var i:Integer;
begin
i:=ExObjList.Add(TQuery.Create(nil));
TQuery(ExObjList.Items[i]).Name:=Name;
TQuery(ExObjList.Items[i]).SQL.Clear;
TQuery(ExObjList.Items[i]).SQL.Add(SQL);
TQuery(ExObjList.Items[i]).Open;
end;
| |
Т.е. все просто создаем новый экземпляр Query и помещаем ссылку на него в ObjectList. В переменной i имеем
индекс расположения в списке, через i затем обращаемся к Query через свойство Item класса TObjectList .
Теперь если необходимо получить какой-нибудь конкретный DataSet вызываем метод GetDataSet с указанием
требуемого имени, получаем ссылку на Query через которую например можем прилинковать Grid:
DataSource1.DataSet:=GetDataSet (Test1);
DbGrid1.DataSource:=DataSource1;
Код метода GetDataSet представлен на листинге 3
Листинг 3.
function TExClass.GetDataSet(Name: TComponentName): TQuery;
var i:Integer;
begin
Result:=nil;
for i:=0 to ExObjList.Count -1 do
if TQuery(ExObjList.Items[i]).Name = Name then
Result:=TQuery(ExObjList.Items[i]);
end; | |
Просто проходим по списку и находим нужный DataSet по имени. Вот собственно и все, если бы не одно но...
Наверное не совсем удобно обращаясь к Item-ам TObjectList-а все время приводить объекты к нужному типу.
Решить это можно так:
Наследуем класс TObjectList и переопределим некоторые методы и свойства следующим образом:
Листинг 4.
TExObjList = class (TObjectList)
protected
procedure Put(Index: Integer; Item: TQuery);
function Get(Index: Integer): TQuery;
public
property Items[Index: Integer]: TQuery read Get write Put; default;
function Add(Obj: TQuery): Integer;
procedure Insert(Index: Integer; Obj: TQuery);
end;
| |
Реализация методов будет такой:
Листинг 5.
function TExObjList.Add(Obj: TQuery): Integer;
begin
Result := inherited Add(Obj);
end;
function TExObjList.Get(Index: Integer): TQuery;
begin
if Count-1 >= Index then
Result := TQuery(inherited Items[Index])
else
Result := nil;
end;
procedure TExObjList.Insert(Index: Integer; Obj: TQuery);
begin
inherited Insert(Index,Obj);
end;
procedure TExObjList.Put(Index: Integer; Item: TQuery);
begin
inherited Items[Index] := Item;
end; | |
Теперь можем обращаться к объектам списка без приведения к типу TQuery. И наш класс - пример
можно теперь оформить так:
Листинг 6.
TExClass = class(TObject)
private
ExObjList:TExObjList;
public
function GetDataSet(Name:TComponentName):TQuery;
procedure NewDataSet(SQL:String;Name:TComponentName);
end;
procedure TExClass.NewDataSet(SQL: String;Name:TComponentName);
var i:Integer;
begin
i:=ExObjList.Add(TQuery.Create(nil));
ExObjList.Items[i].Name:=Name;
ExObjList.Items[i].SQL.Clear;
ExObjList.Items[i].SQL.Add(SQL);
ExObjList.Items[i].Open;
end;
function TExClass.GetDataSet(Name: TComponentName): TQuery;
var i:Integer;
begin
Result:=nil;
for i:=0 to ExObjList.Count -1 do
if ExObjList.Items[i].Name = Name then
Result:=ExObjList.Items[i];
end;
| |
Вот теперь действительно все.
С уважением, Сергей Григорьев
17 февраля 2003
Специально для Королевства Delphi
[TObjectList] [Списки, коллекции] [Классы]
Обсуждение материала [ 21-11-2017 06:27 ] 31 сообщение |