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

FList : TList;

FName : TtdNameString;

protected


function olGetCapacity : integer;

function olGetCount : integer;

function olGetItem(aIndex : integer): TObject;

procedure olSetCapacity(aCapacity : integer);

procedure olSetCount(aCount : integer);

procedure olSetItem(aIndex : integer; aItem : TObject);

procedure olError(aErrorCode : integer; const aMethodName : TtdNameString; aIndex : integer);

public

constructor Create(aClass : TClass;

aDataOwner : boolean);

destructor Destroy; override;


function Add(aItem : TObject): integer;

procedure Clear;

procedure Delete(aIndex : integer);

procedure Exchange(aIndex1, aIndex2 : integer);

function First : TObject;

function IndexOf(aItem : TObject): integer;

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

function Last : TObject;

procedure Move(aCurIndex, aNewIndex : integer);

function Remove(aItem : TObject): integer;

procedure Sort(aCompare : TtdCompareFunc);

property Capacity : integer read olGetCapacity write olSetCapacity;

property Count : integer read olGetCount write olSetCount;

property DataOwner : boolean read FDataOwner;

property Items[Index : integer] : TObject read olGetItem write olSetItem; default;

property List : TList read FList;

property Name : TtdNameString read FName write FName;

end;


Целый ряд методов класса TtdObjectLiet является простыми интерфейсами для вызова соответствующих методов внутреннего класса FList. Например, вот реализация метода TtdObjectList.First:

Листинг 2.11. Метод TtdObjectList.First


function TtdObjectList.First : TObject;

begin

Result := TObject(FList.First);

end;


В тех методах, которые в качестве входного параметра принимают индекс, до вызова соответствующего метода класса FList индекс проверяется на предмет попадания в допустимый диапазон. Строго говоря, эта процедура не обязательна, поскольку сам класс FList будет производить аналогичную проверку, но в случае возникновения ошибки методы класса TtdObjectList позволят получить больший объем информации. Вот один из примеров - метод Move:

Листинг 2.12. Метод TtdObjectList.Move


procedure TtdObjectList.Move(aCurIndex, aNewIndex : integer);

begin

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

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

olError(tdeIndexOutOfBounds, 'Move', aCurIndex);

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

olError(tdeIndexOutOfBounds, 'Move', aNewIndex);

{переместить элементы}

FList.Move(aCurIndex, aNewIndex);

end;


Конструктор класса в качестве входных параметров принимает тип объектов, которые будут храниться в списке (чем обеспечивается безопасность класса к типам), и атрибут владения данными. После этого создается внутренний экземпляр класса FList. Деструктор очищает список и освобождает память, занимаемую списком.

Листинг 2.13. Конструктор и деструктор класса TtdObjectList


constructor TtdObjectList.Create(aClass : TClass; aDataOwner : boolean);

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;


Перейти на страницу:

Похожие книги

C++
C++

С++ – это универсальный язык программирования, задуманный так, чтобы сделать программирование более приятным для серьезного программиста. За исключением второстепенных деталей С++ является надмножеством языка программирования C. Помимо возможностей, которые дает C, С++ предоставляет гибкие и эффективные средства определения новых типов. Используя определения новых типов, точно отвечающих концепциям приложения, программист может разделять разрабатываемую программу на легко поддающиеся контролю части. Такой метод построения программ часто называют абстракцией данных. Информация о типах содержится в некоторых объектах типов, определенных пользователем. Такие объекты просты и надежны в использовании в тех ситуациях, когда их тип нельзя установить на стадии компиляции. Программирование с применением таких объектов часто называют объектно-ориентированным. При правильном использовании этот метод дает более короткие, проще понимаемые и легче контролируемые программы. Ключевым понятием С++ является класс. Класс – это тип, определяемый пользователем. Классы обеспечивают сокрытие данных, гарантированную инициализацию данных, неявное преобразование типов для типов, определенных пользователем, динамическое задание типа, контролируемое пользователем управление памятью и механизмы перегрузки операций. С++ предоставляет гораздо лучшие, чем в C, средства выражения модульности программы и проверки типов. В языке есть также усовершенствования, не связанные непосредственно с классами, включающие в себя символические константы, inline-подстановку функций, параметры функции по умолчанию, перегруженные имена функций, операции управления свободной памятью и ссылочный тип. В С++ сохранены возможности языка C по работе с основными объектами аппаратного обеспечения (биты, байты, слова, адреса и т.п.). Это позволяет весьма эффективно реализовывать типы, определяемые пользователем. С++ и его стандартные библиотеки спроектированы так, чтобы обеспечивать переносимость. Имеющаяся на текущий момент реализация языка будет идти в большинстве систем, поддерживающих C. Из С++ программ можно использовать C библиотеки, и с С++ можно использовать большую часть инструментальных средств, поддерживающих программирование на C. Эта книга предназначена главным образом для того, чтобы помочь серьезным программистам изучить язык и применять его в нетривиальных проектах. В ней дано полное описание С++, много примеров и еще больше фрагментов программ.

Мюррей Хилл , Бьёрн Страуструп , Бьярн Страустрап

Программирование, программы, базы данных / Программирование / Книги по IT