|
Конструктор
Вызывайте наследуемый Метод до реализации
дополнительных действий:
Procedure MyObject.Init(.....);
begin
{Вызов наследуемого конструктора Init}
{Реализация дополнительных действий}
end;
Такая последовательность необходима
по той простой причине, что вызов наследуемого конструктора
приводит к обнулению всех дополнительных полей объекта
MyObject. Если, например, Вы используете следующий фрагмент
программы:
type
MyObject = object (TWindow)
Value: Word;
Ok : Boolean;
Constructor Init(var Bounds: TRect;
ATitle: TTitleStr;
AValue: Word; AOk: Boolean);
end;
Constructor MyObject.Init;
begin
Inherited Init(Bounds, ATitle, wnNoNumber);
Value := 16;
Ok := True;
end;
то дополнительные поля Value и Ok получат
нужные значения 16 и True. Однако, если обращение TWindow.Init
(Bounds, ATitle, wnNoNumber); поставить после оператора
Ok := True, в них будут помещены значения 0 и False.
Из этого правила существует одно исключение, связанное
с загрузкой коллекции из потока конструктором Load.
Дело в том, что в наследуемом методе TCollection.Load
реализуется следующий цикл:
Constructor TCollection.Load (var S:
TStream);
begin
.....
for I := 0 to Count - 1 do
AtPut(I, GetItem(S));
end;
Если элементами коллекции являются произвольные
наборы двоичных данных (не объекты), Вам потребуется
перед чтением очередного элемента сначала получить из
потока его длину. Следующий пример иллюстрирует сказанное.
type
PDataCollection = ATDataCollection;
TDataCollection = object (TStringCollection)
ItemSize: Word;
Constructor Load(var S: TStream);
Function GetItem(var S: TStream): Pointer;
Virtual;
.....
end;
Constructor TDataCollection.Load(var
S: TStream);
begin
S.Read(ItemSize, SizeOf(ItemSize));
Inherited Load(S);
end;
Function TDataCollection.GetItem(var
S: TStream): Pointer;
var
Item: Pointer;
begin
GetMem(Item, ItemSize);
S.Read(Item, ItemSize);
GetItem := Item;
end;
В этом примере конструктор Load сначала
загружает из потока поле ItemSize, содержащее длину
читаемого элемента. Затем вызывается конструктор TCollection.Load,
в котором осуществляется вызов GetItem. Новый GetItem
использует поле ItemSize, чтобы определить размер читаемых
данных, и резервирует нужный буфер в динамической памяти.
Разумеется, запись полиморфных коллекций в поток должна
происходить в том же порядке, т.е. сначала записывается
длина очередного элемента, а уже потом - его данные.
|