Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.11.16;
Скачать: CL | DM;

Вниз

Наследники TList   Найти похожие ветки 

 
Добежал   (2008-09-24 18:19) [0]

Думаю, в любом крупном проекте используется TList, так как постоянно возникает необходимость хранить списки с некоей информацией. И тут возможны два подхода:

1) когда о содержимом TList знает только "вышестоящий" класс, он и типизирует информацию:

TMySuperClass = class(...)
...
 FClientList: TList;
...
end;


Реализация:

constructor TMySuperClass.create;
begin
...
 FClientList := TList.Create;
...
end;

destructor TMySuperClass.destroy;
var
 i: integer;
begin
...
 for i:=0 to FClientList.Count - 1 do
   Dispose(PClientInfo(FClientList[i]));
 FClientList.Free;
end;


Можно немного продвинутей писать (продвинутей ли?), если в классе происходит удаление какого-то клиента во время работы, то ввести функцию DeleteClientByPos:

function DeleteClientByPOS(iPos: integer): boolean;
begin
 if (iPos >=0) and (iPos < FClientList.Count) then
 begin
   Dispose(FClientList[iPos]);
   FClientList.delete(iPos);
   Result := true;
 end
 else Result := false;
end;


Тогда деструктор поменять можно на:

for i:=FClientList.Count-1 downto 0 do
 DeleteClientByPOS(i);


суть не меняется.

2) второй же вариант - это написание каждый раз наследника TList, который будет уметь работать именно с типизированными указателями нужной структуры.

Второй вариант по идеологии правильней, но каждый раз писать... А ведь таких списков может быть десятки, сотни... тысячи. Да и шаблоны дельфи не поддерживает.

Кто как делает? Еще фишка в том, что половина модуля может состоять потом из реализаций TList"ов. Выносить в отдельный модуль uData? Или uLister какой-нибудь ;)

А наверняка еще и парадигма мож какая имеется на эту тему? Жду отзывов кто как делает ;)


 
Ega23 ©   (2008-09-24 18:25) [1]

Наследника. Надо типизированного - пиши типизированного.

for i:=0 to FClientList.Count - 1 do
  Dispose(PClientInfo(FClientList[i]));

Перекрыть Notify в наследнике.


 TGUIDList = class (TList)
 private
   function GetItem(Index: Integer): TGUID;
 protected
   procedure Notify(Ptr: Pointer; Action: TListNotification); override;
 public
   function Add(Item : TGUID) : Integer;
   procedure Clear; override;
   property Items[Index : Integer] : TGUID read GetItem; default;
   function LoadFromStream(ms : TMemoryStream; const BuffLength : Cardinal) : Boolean;
   function SaveToStream(const TagID : Integer; ms : TMemoryStream) : Boolean;
 end;

{ TGUIDList }

//*****************************************************************************

function TGUIDList.Add(Item: TGUID): Integer;
var
 p : PGUID;
begin
 New(p);
 p^ := Item;
 Result := inherited Add(p);
end;

//*****************************************************************************

procedure TGUIDList.Clear;
var
 i : Integer;
 p : Pointer;
begin
 for i:=0 to Count-1 do
 begin
   p := Get(i);
   Dispose(PGUID(p));
 end;
 inherited;
end;

//*****************************************************************************

function TGUIDList.GetItem(Index: Integer): TGUID;
begin
 Result := PGUID(Get(Index))^;
end;

//*****************************************************************************

function TGUIDList.LoadFromStream(ms: TMemoryStream;
 const BuffLength: Cardinal): Boolean;
var
 guid : TGUID;
 i, cnt : Integer;
 recSize : Cardinal;
begin
 try
   Result := True;
   Clear;
   recSize := SizeOf(TGUID);
   cnt := BuffLength div recSize;
   if cnt=0 then Exit;
   for i:=1 to cnt do
   begin
     ms.ReadBuffer(guid, recSize);
     Add(guid);
   end;
 except
   Clear;
   Result := False;
 end;
end;

//*****************************************************************************

procedure TGUIDList.Notify(Ptr: Pointer; Action: TListNotification);
begin
 inherited;
 if Action in [lnExtracted, lnDeleted] then
   Dispose(PGUID(Ptr));
end;

//*****************************************************************************

function TGUIDList.SaveToStream(const TagID: Integer;
 ms: TMemoryStream): Boolean;
var
 i : Integer;
 BuffLen : Cardinal;
 guid : TGUID;
begin
 try
   ms.WriteBuffer(TagId, 4);
   BuffLen := Count*SizeOf(TGUID);
   ms.WriteBuffer(BuffLen, 4);
   for i:=0 to Count-1 do
   begin
     guid := Items[i];
     ms.WriteBuffer(guid, SizeOf(TGUID));
   end;
   Result := True;
 except
   Result := False;
 end;
end;

//*****************************************************************************



 
Ega23 ©   (2008-09-24 18:26) [2]

А в целом - есть TObjectList, который прекрасно вызывает деструкторы своих объектов, если надо.


 
Поросенок Винни-Пух ©   (2008-09-24 18:26) [3]

Третий вариант. Радикальный.
Вообще отказаться от листов с рекордами. Что я и сделал.


 
oldman ©   (2008-09-24 18:28) [4]


> А ведь таких списков может быть десятки, сотни... тысячи.


Ты чего там пишешь?


 
Поросенок Винни-Пух ©   (2008-09-24 18:34) [5]

Кроме третьего варианта есть еще дав с половиной.
Если вся загвоздка в типе для диспоза, то ведь сам тип можно сделать параметром и передавать в десруктор элемента списка


 
Sergey Masloff   (2008-09-24 21:05) [6]

Почему не нужно наследоваться от TList написано у Бакнела. У меня нет доводов которые я могу ему противопоставить.


 
Добежал   (2008-09-24 21:08) [7]


> А в целом - есть TObjectList, который прекрасно вызывает
> деструкторы своих объектов, если надо


понятно, но это если хранить классы. У меня зачастую хранятся именно структуры аля:

TClientInfo = record
 Name:
 Family:
 Date
bla bla
end;


С другой стороны каждую структуру можно сделать классом... Будет такой аля java подход ;)


> Вообще отказаться от листов с рекордами. Что я и сделал


типа такая попытка вызвать интерес и нарваться на вопрос уточняющий. А я не буду задавать вопрос. Отказался - и молодец ;)


 
guav ©   (2008-09-24 21:14) [8]

уже ж появились дженерики, нет ? ;)


 
DVM ©   (2008-09-24 21:32) [9]

Я за первый вариант.


 
guav ©   (2008-09-24 21:44) [10]

Удаление из середины вообще нужно ? А констатное время доступа к элементу по его номеру в списке ?

> Жду отзывов кто как делает ;)

Я не писал наследников, использовал TObjectList напрямую.


 
jack128_   (2008-09-24 21:56) [11]


> Да и шаблоны дельфи не поддерживает.

Ну собственно
> уже ж появились дженерики
это я только вернувшись к семинара..


 
Eraser ©   (2008-09-24 23:39) [12]

> [8] guav ©   (24.09.08 21:14)

+1 )


 
MsGuns ©   (2008-09-24 23:52) [13]

Я вообще не понял к чему сабж. Это типа "Чуваки, я завязал кушать мясо и чувствую себя зашибись !" ?


 
Ega23 ©   (2008-09-25 00:10) [14]


> Я не писал наследников, использовал TObjectList напрямую.


Напрямую не всегда удобно, приводить Items[i] всегда надо.


 
guav ©   (2008-09-25 00:52) [15]

> [14] Ega23 ©   (25.09.08 00:10)


> Напрямую не всегда удобно, приводить Items[i] всегда надо.

Ага. А ещё в обработчики событий Sender приходит как TObject, приводить его к нужному типу неудобно. В Делфи даункастинг - норма.


 
Германн ©   (2008-09-25 01:21) [16]


> А ещё в обработчики событий Sender приходит как TObject,
>  приводить его к нужному типу неудобно.

Устойчивая привычка проверять и приводить типы закладывается довольно быстро.


 
Real ©   (2008-09-25 01:43) [17]


> Ага. А ещё в обработчики событий Sender приходит как TObject

Согласен, раздражало(ет) это всегда


 
Германн ©   (2008-09-25 01:48) [18]


> Real ©   (25.09.08 01:43) [17]
>
>
> > Ага. А ещё в обработчики событий Sender приходит как TObject
>
> Согласен, раздражало(ет) это всегда
>

И чем раздражало?


 
brother ©   (2008-09-25 03:18) [19]

> И чем раздражало?

Лишние телодвижения? ;)


 
GrayFace ©   (2008-09-25 05:09) [20]

Еще вариант - использовать GetMem/FreeMem, а у списка сдалать свойство ItemSize. Хотя для record"ов лучше массив.


 
korneley ©   (2008-09-25 06:33) [21]

Я как-то не заморачивался, делал, типа:

 TRange = class
  ipStart,
  ipEnd   : TAddr;
  Checked : boolean;
 end;

 TRangeList = class(TObjectList)
   function GetItem(Index: Integer): TRange;
   procedure SetItem(Index: Integer; AObject: TRange);
 public
   property Items[Index: Integer]: TRange read GetItem write SetItem; default;
 end;
...
{ TRangeList }

function TRangeList.GetItem(Index: Integer): TRange;
begin
 Result := TRange(inherited Items[Index]);
end;

procedure TRangeList.SetItem(Index: Integer; AObject: TRange);
begin
 inherited Items[Index] := AObject;
end;

Ибо, что ещё "впихнуть" в рекорд (который вдруг становится классом) понадобится - не всегда заранее известно.


 
Медвежонок Пятачок ©   (2008-09-25 08:09) [22]

я отказался от TList с рекордами вообще.
использую ixmldomdocument2.
сразу убивается целое стадо зайцев.


 
Добежал   (2008-09-25 11:24) [23]


> Почему не нужно наследоваться от TList написано у Бакнела.
>  У меня нет доводов которые я могу ему противопоставить


эээ... TList специально сделан, чтобы от него удобно было наследоваться по идее то...

А можно таки узнать, почему не нужно наследоваться от TList?


 
Поросенок Винни-Пух ©   (2008-09-25 11:31) [24]

потому что рано или поздно начинаешь задаваться над вопросом:
"а зачем мне постоянно убивать время на поддержку многочисленных классов рекордов, что нет занятий более интересных, чем эта рутина?"


 
Palladin ©   (2008-09-25 11:35) [25]


> А можно таки узнать, почему не нужно наследоваться от TList?

ну не знаю как там другие, но, лично я, никогда не наследуюсь от TList и всегда создаю класс его агрегирующий, что позволяет всегда, прозрачно для программиста-клиента, заменить его на какой либо другой контейнер


 
MsGuns ©   (2008-09-25 11:38) [26]

>Добежал   (25.09.08 11:24) [23]
>А можно таки узнать, почему не нужно наследоваться от TList?

Потому же, почему не имеет смысл изобретать модификации зубила. Оно само по себе достаточно функционально, а если приспичило сверлить или закручивать гайки, то для этого имеются другие, более пригодные инструменты. О чем здесь Вам талдычат два десятка постов


 
Поросенок Винни-Пух ©   (2008-09-25 12:15) [27]

берешь xml документ.
придумывешь иерархию узлов для хранения своих многочисленных структур.
создаешь один раз на всю оставшуюся жизнь несколько библиотечных функций  для извлечения данных.
все.

доспуп к данным превращается из императивного в декларативный.
удобно хранить, просто сериализировать, легко визуализировать и редактировать. гибкость просто на высоте.

никаких многочисленных TMyRecord = record end;
никаких тысяч и тысяч строк рутинного кода каждый раз когда нужна новая структура.

Все есть, юзай-не хочу.

Не хочется обрабатывать на клиенте - отдал xml sql серверу и наоборот.
От возможностей глаза разбегаются.
Туча времени высвобождается на решение действительно творческих задач.


 
guav ©   (2008-09-25 12:42) [28]

Что вообще нужно от контейнера ?
Удаление из середины вообще нужно ?
А констатное время доступа к элементу по его номеру в списке ?
Нужен ли полиморфизм (подозреваю что нет, т.к. речь о рекордах) ?
Нужна ли сортировка ?


 
Добежал   (2008-09-25 12:53) [29]


> берешь xml документ.
> придумывешь иерархию узлов для хранения своих многочисленных
> структур.
> создаешь один раз на всю оставшуюся жизнь несколько библиотечных
> функций  для извлечения данных.
> все.
>
> доспуп к данным превращается из императивного в декларативный.
>
> удобно хранить, просто сериализировать, легко визуализировать
> и редактировать. гибкость просто на высоте.
>
> никаких многочисленных TMyRecord = record end;
> никаких тысяч и тысяч строк рутинного кода каждый раз когда
> нужна новая структура.


выглядит привлекательно, но я не понял. Можно пример?

to guav, не могу тебе ответить на твои вопросы. Речь идет не о конкретной разработке, а вообще о подходах...


 
Поросенок Винни-Пух ©   (2008-09-25 14:09) [30]

Для примера нужен пример задачи


 
Добежал   (2008-09-25 16:50) [31]


> Для примера нужен пример задачи


не могу придумать пример, не зная всех прелестей технологии. Наверное, тебе легче составить пример задачи, реализация которой во всей красе выявит гибкость подхода.


 
Ega23 ©   (2008-09-25 16:55) [32]


> выглядит привлекательно, но я не понял. Можно пример?


Не надо, он фанат xml. Он бы на самом xml всё писал, если бы тот ЯП был.


 
Поросенок Винни-Пух ©   (2008-09-25 17:02) [33]

не могу придумать пример, не зная всех прелестей технологии.

прелести я покажу, но нужен пример. у меня их своих конечно куча, но доходчивей будет если, задача будет не моя.


 
KSergey ©   (2008-09-25 17:19) [34]

> Поросенок Винни-Пух ©   (25.09.08 12:15) [27]
> берешь xml документ.

Это все прикольно, когда вообще нет требований по скорости, да и по объему не особо. Зато надо визуализировать/редактировать/серилизовать (ёпрс! всегда любил это слово за возможность описки)

Во всех других случаях это совершенно неподходящее решение.


 
Поросенок Винни-Пух ©   (2008-09-25 17:25) [35]

Во всех других случаях это совершенно неподходящее решение.

да не надо ля-ля.
Ну есть сто тысяч элементов списка по тридцать три поля.

Что я загоню все в xml, что вы насоздаете все сто тысяч экземпляров рекордов.


 
Поросенок Винни-Пух ©   (2008-09-25 17:28) [36]

если бы тот ЯП был

В некотором смысле он и есть яп.
особенно xsl


 
Sapersky   (2008-09-25 19:49) [37]

Еще вариант - использовать GetMem/FreeMem, а у списка сдалать свойство ItemSize. Хотя для record"ов лучше массив.

Можно сделать универсальный список/массив и с New/Dispose (точнее, system._Initialize/_Finalize), будет поддержка длинных строк и прочих автоматически финализируемых элементов в записях.


 
DVM ©   (2008-09-25 21:08) [38]


> Что я загоню все в xml, что вы насоздаете все сто тысяч
> экземпляров рекордов.

особенно бинарные данные там хорошо будут смотреться особенно в плане скорости добавления/удаления


 
Ega23 ©   (2008-09-25 21:12) [39]


> особенно бинарные данные там хорошо будут смотреться особенно
> в плане скорости добавления/удаления


Зато это не ini-файлы и xPath есть.
Ничего ты не понимаешь.


 
DVM ©   (2008-09-25 21:19) [40]


> Ничего ты не понимаешь.

Я действительно не понимаю зачем пихать всюду XML, заменяя им все и вся и пытаясь прикрутить его вместо удобных и проверенных временем вещей.



Страницы: 1 2 3 вся ветка

Текущий архив: 2008.11.16;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.016 c
2-1223287456
Dennis I. Komarov
2008-10-06 14:04
2008.11.16
MDI из DLL


2-1223495398
АгатаКристи
2008-10-08 23:49
2008.11.16
IP, Основной Шлюз, DNS


15-1221727773
m2804
2008-09-18 12:49
2008.11.16
downgrade с Vista на XP


15-1221658793
Terasbetoni
2008-09-17 17:39
2008.11.16
3Д-движок, работающий с кривыми поверхностями.


15-1221421673
kaif
2008-09-14 23:47
2008.11.16
Uriah Heep Sympathy