Для того чтобы правильно проинициализировать в создаваемом объекте поля, относящиеся к классу-предку, нужно сразу же при входе в конструктор вызвать конструктор предка:
constructorTmyObject.Create;
begin
inheritedCreate;
…
end;
Метод Create объекта MyObject типа TMyObject унаследован от класса предка TObject.
Взяв любой из примеров, поставляемых вместе с Delphi, мы обнаружим, что там почти нет вызовов конструкторов и деструкторов. Дело в том, что любой компонент, попавший при визуальном проектировании в приложение из Палитры компонентов, включается в определенную иерархию. Иерархия эта замыкается на форме (TForm): для всех ее составных частей конструкторы и деструкторы вызываются автоматически, незримо для программиста.
Кто создает и уничтожает формы? Это делает приложение (глобальный объект с именем Application). В файле проекта (.DPR) можно увидеть вызов функции CreateForm, предназначенный для этой цели. Что же касается объектов, создаваемых динамически (во время выполнения приложения), то здесь нужен явный вызов конструктора.
6. НАСЛЕДОВАНИЕ
Вторым "столпом" ООП, помимо инкапсуляции, является наследование. Этот простой принцип означает, что если нужно создать новый класс, лишь немного отличающийся от старого, то совершенно нет необходимости в переписывании заново уже существующих полей и методов. Новый класс
TNewObject = class(TOldObject);
является потомком, или дочерним классом старого класса, называемого предком, или родительским классом. Добавляются к нему лишь новые поля, методы и свойства.
В Object Pascal все классы являются потомками класса TObject. Поэтому если строится дочерний класс прямо от TObject, то в определении TOject можно не упоминать. Следующие два выражения одинаково верны:
TMyObject = class(TObject);
TMyObject = class;
Использование последнего выражения оправдано, если разработчик хочет показать, что, согласно его замыслу, проектируемый класс как бы не имеет предков.
Приведем объявление базового для всех объектных типов класса TObject:
TObject = class
constructorCreate;
destructorDestroy; virtual;
procedureFree;
class functionNewlnstance: TObject; virtual;
procedureFreelnstance; virtual;
class procedureInitlnstance(Instance: Pointer):
TObject;
functionClassType: TClass;
class functionClassName: string;
class functionClassParent: TClass;
class functionClassInfo: Pointer;
class functionInstanceSize: Word;
class functionInheritsFrom(AClass: TClass):
Boolean;
procedureDefaultHandler(var Message); virtual;
procedureDispatch(var Message);
class functionMethodAddress(const Name: string):
Pointer;
class functionMethodName(Address: Pointer):
string;
function FieldAddress(const Name: string):
Pointer;
end;
Такая архитектура возможна только при наличии механизма поддержки информации о типах — RTTI (RunTime Type Information). Основой такого механизма является внутренняя структура классов и, в частности, возможность доступа к ней за счет использования методов классов, описываемых конструкцией class function…
Унаследованные от предка поля и методы доступны в дочернем классе; если имеет место совпадение имен методов, то эти методы перекрываются.
По тому, какие действия происходят при вызове, методы делятся на группы:
• статические ( static);
• виртуальные ( virtual);
• динамические ( dynamic);
• абстрактные ( abstract).
Статические методы, а также поля в объектах-потомках ведут себя одинаково: можно без ограничений перекрывать старые имена и при этом изменять тип методов:
type
T1stObj = class
I: Real;
procedureSetData(Avalue: Real);
end;
T2ndObj = class(T1stObj)
I: Integer;
procedureSetData(Avalue: Integer);
end;
…
procedureT1stObj.SetData;
begin
i: = v;
end;
procedureT2nd0bj.SetData;
begin
i:= 0;
inheritedSetData(0.99);
end;
В этом примере разные методы с именем SetData присваивают значения разным полям с именем i. Перекрытое поле предка недоступно в потомке. В отличие от поля внутри других методов перекрытый метод доступен при указании зарезервированного слова inherited. Методы объектов по умолчанию являются статическими — их адрес определяется еще на стадии компиляции проекта. Они вызываются быстрее всего.
Читать дальше