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



И что еще хуже с точки зрения объектно-ориентированного программирования, мы получили ситуацию, когда для поддержки производного класса был изменен родительский класс. TList не должен освобождать свои элементы - это стало правилом еще с версии Delphi1. Тем не менее, он был изменен для того, чтобы такая возможность поддерживалась его дочерними классами (а фактически только одним классом из VCL Delphi 5 - классом TObjectList).

Денни Торп (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, и после этого уже не будет возможности изменить тип владения данными.