Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Наследники TList


Страницы:   1 2 3 4 5

Добежал ©   (2008-09-24 18:19:00) 

Думаю, в любом крупном проекте используется 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-25 00:10:00) [81]


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


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


MsGuns   (2008-09-24 23:52:00) [82]

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


Eraser   (2008-09-24 23:39:00) [83]

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

+1 )


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


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

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


guav   (2008-09-24 21:44:00) [85]

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

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

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


DVM   (2008-09-24 21:32:00) [86]

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


guav   (2008-09-24 21:14:00) [87]

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


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


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


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

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


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


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


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


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

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


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

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


oldman   (2008-09-24 18:28:00) [91]


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


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


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

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


Ega23   (2008-09-24 18:26:00) [93]

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


Ega23   (2008-09-24 18:25:00) [94]

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

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;

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


Страницы:   1 2 3 4 5

Наверх

Титульная страница Поиск, карта сайта Написать письмо