Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2008.11.16;
Скачать: [xml.tar.bz2];

Вниз

Наследники 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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.56 MB
Время: 0.007 c
2-1223200633
AlexDan
2008-10-05 13:57
2008.11.16
RichEdit..


15-1221562788
desc
2008-09-16 14:59
2008.11.16
Как в Dll работать с набором данных ?


15-1221712150
KilkennyCat
2008-09-18 08:29
2008.11.16
О японцах и русском языке.


2-1222265965
Добежал
2008-09-24 18:19
2008.11.16
Наследники TList


3-1209750958
Beer_Hunter
2008-05-02 21:55
2008.11.16
Параметризированный запрос





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский