Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Книга о KOL.doc
Скачиваний:
29
Добавлен:
30.04.2019
Размер:
1.77 Mб
Скачать

2.9.2. Наследование объектов от tObj

Немного забегая вперед, остановлюсь на процедуре создания своего наследника от TObj. Дело в том, что обычно проекты KOL создаются с активным использованием объектного подхода, и TObj является идеальным предком для всех простых объектов, которые могут вам понадобиться для реализации своих целей.

А именно, следует обратить внимание на использование метода Init и деструктора Destroy. В переопределенном виртуальном методе Init желательно разместить инициализацию объекта, а именно, ту часть этой инициализации, которая не зависит от каких-либо параметров. Разумеется, можно для каждого своего объекта оформлять глобальную функцию NewXXXX, аналогично тому, как это делается в самом модуле KOL.pas. Но на самом деле, если все такие функции не будут иметь параметров, то смысла в такой работе вовсе нет и проще обойтись вызовом конструктора в стиле Turbo Pascal вида:

New( MyVar, Create );

О

тмечу здесь особо: в отличие от классов, здесь вы должны освободить все ресурсы, принадлежащие объекту, самостоятельно. А именно: все поля, являющиеся объектами, и создаваемые на время существования именно этого объекта (вызов метода Free). Все динамические участки памяти, выделенные по AllocMemory или GetMem (вызов функции FreeMem). Все динамические массивы (вызов SetLength с параметром размера, равным 0). Все варианты (присваивание Unassigned). Все ANSI-строки (присваивание пустой строки). Обратите внимание на последний пункт (строки): это самый распространенный источник утечек памяти при работе в простыми объектами в KOL-проектах.

Если вы наследуете свой объектный тип непосредственно от типа TObj, то вызывать метод inherited в своей реализации метода Init особой необходимости нет (в самом объекте TObj этот метод ничего не делает).

И даже в случае наличия конструирующей функции желательно ту часть инициализации объекта, которая не зависит от параметров, выносить в метод Init. И не забудьте, что при работе в простыми объектами слово override в вашем определении метода Init не должно использоваться: вместо этого следует опять использовать слово virtual (см. пример справа).

type

PmyType = ^TmyType;

TmyType = object( Tobj)

Protected

MyStrProp: string;

MyStrList: PStrList;

procedure Init;virtual;

destructor Destroy;virtual;

// implementation:

procedure TmyType.Init;

begin

//inherited; - не нужен

MyStrProp := ’OK’;

MyStrList := NewStrList;

end;

Аналогично, для деструктора Destroy: пишем virtual вместо override. Но inherited вызывать необходимо, причем обычно перед выходом из деструктора, когда уже все свои действия по освобождению более не нужных ресурсов выполнены. Иногда какие-то действия могут выполняться и после вызова унаследованного деструктора (inherited), но это уже ни в коем случае не должны быть обращения к полям удаленного объекта. Сразу после возврата из inherited объект более не существует в памяти, и попытка доступа к ним может привести к фатальным для программы последствиям.

destructor TmyType.Destroy;

begin

MyStrProp := ’’;

MyStrList.Free;

inherited; // нужен обязательно

end;