52704.fb2 Фундаментальные алгоритмы и структуры данных в Delphi - читать онлайн бесплатно полную версию книги . Страница 15

Фундаментальные алгоритмы и структуры данных в Delphi - читать онлайн бесплатно полную версию книги . Страница 15

Денни Торп (Denny Thorpe), один из самых толковых разработчиков в отделе научных исследований компании Borland, в своей книге "Разработка компонент Delphi" (Delphi Component Design) [23] сказал следующее:

"TList - это рабочая лошадка, а не порождающий класс... При необходимости использования списка создайте простой интерфейсный класс (порожденный от TObject, а не от TList), который будет иметь только нужные вам эквиваленты свойств и функций TList, и возвращаемые типы значений функций и параметров методов которого соответствуют типу хранящихся в списке данных. В таком случае интерфейсный класс будет содержать в себе класс TList и использовать его для хранения данных. Реализуйте функции и методы доступа к свойствам этого интерфейсного класса в виде однострочных вызовов соответствующих методов или свойств внутреннего класса TList с применением соответствующих преобразований типов".

Очень жаль, что книга Денни Торпа не внесена в перечень книг, обязательных для прочтения в отделе научных исследований компании Borland.

Класс TtdObjectList

А сейчас мы создадим новый класс списка, который работает как TList, но имеет два отличия: он хранит экземпляры некоторого класса (или его дочерних классов) и при необходимости уничтожает все содержащиеся в нем объекты. Другими словами, это будет специализированный список, в котором не будет двух описанных в предыдущем разделе недостатков. Назовем наш класс TtdObjectList. Он отличается от класса TObjectList в Delphi 5 и более поздних версиях тем, что будет безопасным к типам.

Он не будет дочерним классом TList. Конечно, в нем будут содержаться те же методы, но их реализация будет основана на делегировании к методам с теми же именами внутреннего класса TList.

Класс TtdObjectList имеет один новый очень важный атрибут - владение данными. Это класс будет функционировать либо точно так же, как TList, т.е. при уничтожении его элементы не будут освобождаться (он не владеет данными), либо будет иметь полный контроль над своими элементами и при необходимости будет их удалять (он владеет данными). Установка атрибута владения данными выполняется при создании экземпляра класса TtdObjectList, и после этого уже не будет возможности изменить тип владения данными.

Кроме того, класс будет обеспечивать безопасность к типам (type safety). При создании экземпляра класса, необходимо указывать какой тип (или класс) объектов будет в нем храниться. Во время добавления или вставки нового элемента специальный метод будет проверять соответствие типа нового объекта объявленному типу элементов списка.

Интерфейс класса TtdObjectList напоминает интерфейс класса TList. В нем не реализован метод Pack, поскольку в список будут добавляться только объекты, не равные nil. Подробное описание метода Sort будет приведено в главе 5.

Листинг 2.10. Объявление класса TtdObjectList

TtdObjectList = class private

FClass : TClass;

FDataOwner : boolean;

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;