Чтение онлайн

на главную - закладки

Жанры

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

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

Шрифт:

begin

inherited Create;

{сохранить класс и флаг владения данными}

FClass := aClass;

FDataOwner := aDataOwner;

{создать внутренний список}

FList := TList.Create;

end;

destructor TtdObjectList.Destroy;

begin

{если список содержит элементы, очистить их и уничтожить список}

if (FList <> nil) then begin

Clear;

FList.Destroy;

end;

inherited Destroy;

end;

Если вы не уверены, каким образом передавать значение параметра aClass, приведем

пример с использованием класса TButton:

var

MyList : TtdObjectList;

begin

• • •

MyList := TtdObjectList.Create(TButton, false);

Первым реальным отличием нового списка от стандартного класса TList является метод Clear. Он предназначен для проверки того, владеет ли список данными. В случае положительного результата, перед уничтожением списка все его элементы будут удалены. (Обратите внимание, что здесь для удаления каждого отдельного элемента не используется метод Delete класса FList. Намного эффективнее очищать список после освобождения памяти, занимаемой его элементами.)

Листинг 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.

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

Дракон - не подарок

Суббота Светлана
2. Королевская академия Драко
Фантастика:
фэнтези
6.74
рейтинг книги
Дракон - не подарок

Бастард Императора. Том 8

Орлов Андрей Юрьевич
8. Бастард Императора
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 8

Чужая дочь

Зика Натаэль
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Чужая дочь

Эра Мангуста. Том 2

Третьяков Андрей
2. Рос: Мангуст
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Эра Мангуста. Том 2

Идеальный мир для Лекаря 14

Сапфир Олег
14. Лекарь
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 14

Один на миллион. Трилогия

Земляной Андрей Борисович
Один на миллион
Фантастика:
боевая фантастика
8.95
рейтинг книги
Один на миллион. Трилогия

Помещицы из будущего

Порохня Анна
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Помещицы из будущего

Шлейф сандала

Лерн Анна
Фантастика:
фэнтези
6.00
рейтинг книги
Шлейф сандала

Черный маг императора 2

Герда Александр
2. Черный маг императора
Фантастика:
юмористическая фантастика
попаданцы
аниме
6.00
рейтинг книги
Черный маг императора 2

Император

Рави Ивар
7. Прометей
Фантастика:
фэнтези
7.11
рейтинг книги
Император

Бандит 2

Щепетнов Евгений Владимирович
2. Петр Синельников
Фантастика:
боевая фантастика
5.73
рейтинг книги
Бандит 2

На границе империй. Том 9. Часть 2

INDIGO
15. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 2

Князь Серединного мира

Земляной Андрей Борисович
4. Страж
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Князь Серединного мира

Чайлдфри

Тоцка Тала
Любовные романы:
современные любовные романы
6.51
рейтинг книги
Чайлдфри