Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Hello, World!
  
 

Фильтр по датам

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  15:54[Войти] | [Зарегистрироваться]

Удобная оперативность. Класс TObjectList

Сергей Григорьев
дата публикации 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; // это наш контейнер для DataSet-ов
public
  { здесь тоже}
  function GetDataSet(Name:TComponentName):TQuery; // а так обеспечим обращение к любому из них
  procedure NewDataSet(SQL:String;Name:TComponentName); // здесь будем генерировать каждый новый DataSet и
 	                              //  сохранять его в контейнере 
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)); // помещаем в контейнер ссылку на
                                              // экземпляр DataSetа
  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          // проверка на правильность Index-а,иначе
    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; // это наш контейнер для DataSet-ов
public
  { здесь тоже}												   
  // а так обеспечим обращение к любому из них
  function GetDataSet(Name:TComponentName):TQuery;
  // здесь будем генерировать каждый новый DataSet и
  // сохранять его в контейнере  
  procedure NewDataSet(SQL:String;Name:TComponentName); 

end;

procedure TExClass.NewDataSet(SQL: String;Name:TComponentName);
var i:Integer;
begin
  i:=ExObjList.Add(TQuery.Create(nil)); // помещаем в контейнер ссылку на
                                              // экземпляр DataSetа
  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 сообщение
  
Время на сайте: GMT минус 5 часов

Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
Функция может не работать в некоторых версиях броузеров.

Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

 
© При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
Все используемые на сайте торговые марки являются собственностью их производителей.

Яндекс цитирования