Форум: "Начинающим";
Текущий архив: 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