Вход/Регистрация
Фундаментальные алгоритмы и структуры данных в Delphi
вернуться

Бакнелл Джулиан М.

Шрифт:

Листинг 2.14. Метод TtdObjectList.Clear

procedure TtdObjectList.Clear;

var

i : integer;

begin

{если данные принадлежат списку, перед очисткой списка освобождаем память, занимаемую элементами}

if DataOwner then

for i := 0 to pred(FList.Count) do

TObject(FList[i]).Free;

FList.Clear;

end;

Методы Delete и Remove перед удалением выполняют один и тот же тип проверки, и если список владеет данными, объект освобождается, после чего удаляется и список. Обратите внимание, что в методе Remove используется не вызов метода FList.Remove, а полная реализация метода. Такой подход называется "кодированием на основе главных принципов". Он обеспечивает более глубокий контроль и дает более высокую эффективность.

Листинг 2.15. Удаление элемента из списка TtdObjectList

procedure TtdObjectList.Delete(aIndex : integer);

begin

{проверяем индексы сами, а не перекладываем эту обязанность на список}

if (aIndex < 0) or (aIndex >= FList.Count) then

olError(tdeIndexOutOfBounds, 'Delete', aIndex);

{если список владеет объектами, освобождаем память, занимаемую удаляемым элементом}

if DataOwner then

TObject(FList[aIndex]).Free;

{удалить элемент из списка}

FList.Delete(aIndex);

end;

function TtdObjectList.Remove(aItem : TObject): integer;

begin

{найти требуемый элемент}

Result := IndexOf(aItem);

{если элемент найден...}

if (Resul <> -1) then begin

{если список владеет объектами, освобождаем память, занимаемую удаляемым элементом}

if DataOwner then

TObject(FList[Result]).Free;

{удалить элемент из списка}

FList.Delete(Result);

end;

end;

В методе olSetItem (метод записи свойства Items массива), который устанавливает значение или вставляет элемент в список, можно обнаружить небольшой недостаток. Предположим, что программист написал следующий блок кода:

var

MyObjectList : TtdObjectList;

SomeObject : TObject;

begin

• • •

MyObjectList[0] := SomeObject;

Все кажется довольно-таки безобидным, но подумайте, что случится, если данные принадлежат списку. В результате выполнения оператора присваивания элемент с индексом 0 будет замещен новым объектом, SomeObject. Предыдущий объект будет безвозвратно потерян, и ссылки на него окажутся недействительными. Таким образом, перед заменой старый объект нужно освободить. Конечно, сначала следует проверить принадлежит ли новый объект к требуемому типу.

Листинг 2.16. Запись элемента в TtdObjectList

procedure TtdObjectList.olSetItem(aIndex : integer;

aItem : TObject);

begin

{проверить тип элемента}

if (aItem = nil) then

olError(tdeNilItem, 'olSetItem', aIndex);

if not (aItem is FClass) then

olError(tdeInvalidClassType, 'olSetItem', aIndex);

{проверяем индексы сами, а не перекладываем эту обязанность на список}

if (aIndex < 0) or (aIndex >= FList.Count) then

olError(tdeIndexOutOfBounds, 'olSetItem', aIndex);

{если список владеет объектами и объект с текущим индексом должен быть заменен новым объектом, сначала освобождаем старый объект}

if DataOwner and (aItemoFList [aIndex]) then

TObject(FList[aIndex]).Free;

{сохранить в списке новый объект}

FList[aIndex] := aItem;

end;

И, наконец, рассмотрим методы Add и Insert. Как и Remove, метод Add написан с учетом главных принципов, поэтому вместо FList.Add используется FList.Insert.

Листинг 2.17. Методы Add и Insert класса TtdObjectList

function TtdObjectList.Add(aItem : TObject): integer;

begin

{проверить тип элемента}

if (aItem = nil) then

olError(tdeNilItem, 'Add', FList.Count);

if not (aItem is FClass) then

olError(tdeInvalidClassType, 'Add', FList.Count);

{вставить новый элемент в конец списка}

Result := FList.Count;

FList.Insert(Result, aItem);

end;

procedure TtdObjectList.Insert(aIndex : integer; aItem : TObject);

begin

{проверить тип элемента}

if (aItem = nil) then

olError(tdeNilItem, 'Insert', aIndex);

if not (aItem is FClass) then

olError(tdeInvalidClassType, 'Insert', aIndex);

{проверяем индексы сами, а не перекладываем эту обязанность на список}

if (aIndex < 0) or (aIndex > FList.Count) then

olError(tdeIndexOutOfBounds, 'Insert', aIndex);

{вставить новый элемент в список}

FList.Insert(aIndex, aItem);

end;

Полный код класса TtdObjectList можно найти на Web-сайте издательства, в разделе материалов. После выгрузки материалов отыщите среди них файл TDObjLst.pas.

  • Читать дальше
  • 1
  • ...
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: