Delphi 7. Занятие 2_7. Часть 2.
Цели занятия.
- иерархия классов;
- структура класса TObject;
- структура класса TClass;
- группы методов, составляющих класс;
- пример использования метода класса;
- роль конструктора объекта; конструктор create;
- пример создания экземпляра объекта;
Классы дочерние и родительские
В части 1 говорилось о механизме наследования. Рассмотрим его действие на примере. Будем создавать иерархию классов, начиная от базового класса TObject.
Посмотрим на методы базового класса TObject и дадим комментарии к некоторым из них.
Во первых, это методы, которые даже сгруппированы в отдельный класс TClass.
Далее дан полный перечень методов класса TObject.
Если посмотреть внимательно, то можно увидеть, что методы класса TClass являются составной частью класса TObject, но помечены директивой «class»:
TObject = class constructor Create; procedure Free; class function InitInstance(Instance: Pointer): TObject; procedure CleanupInstance; function ClassType: TClass; class function ClassName: ShortString; class function ClassNameIs(const Name: string): Boolean; class function ClassParent: TClass; class function ClassInfo: Pointer; class function InstanceSize: Longint; class function InheritsFrom(AClass: TClass): Boolean; class function MethodAddress(const Name: ShortString): Pointer; class function MethodName(Address: Pointer): ShortString; function FieldAddress(const Name: ShortString): Pointer; function GetInterface(const IID: TGUID; out Obj): Boolean; class function GetInterfaceEntry(const IID: TGUID): PInterfaceEntry; class function GetInterfaceTable: PInterfaceTable; function SafeCallException(ExceptObject: TObject; ExceptAddr: Pointer): HResult; virtual; procedure AfterConstruction; virtual; procedure BeforeDestruction; virtual; procedure Dispatch(var Message); virtual; procedure DefaultHandler(var Message); virtual; class function NewInstance: TObject; virtual; procedure FreeInstance; virtual; destructor Destroy; virtual; end;
Просмотрев содержание класса TObject, можно выделить четыре группы записей.
Это:
1) конструктор «constructor Create» и деструктор «destructor Destroy».
2) Функции и процедуры, помеченные директивой «virtual» (а также директивой «dinamic»; в классе TObject она отсутствует).
3) Функции и процедуры, которым предшествует ключевое слово class.
4) Функции и процедуры, не помеченные директивами «dinamic», «virtual» и class.
Функции и процедуры, не помеченные директивами «dinamic» и «virtual», называются статическими.
Под статические процедуры и функции распределение памяти происходит при компиляции программы. То есть, использовать такие функции и процедуры можно, не создавая экземпляр объекта данного класса в динамической памяти.
Рассмотрим пример. Создадим новый класс на основе класса TObject.
Type
TMyClass=class(TObject)
ii:integer; //ввели новое поле, которого нет в TObject.
end;
Объявим переменную класса TMyClass и посмотрим, какие методы оказываются доступны без создания экземпляра объекта.
Мы видим, что можно напрямую обратиться к функциям и процедурам, имеющим директиву «class» (о директиве «class» смотри выше).
Замечание.
Компилятор не отводит память под поле ii, хотя наличие поля отображается в составе класса. Память под поля объекта будет распределена при создании экземпляра объекта.
Действительно, экземпляров данного класса может быть создано несколько, и у каждого может быть собственное значение поля.
Проиллюстрируем доступ к статическим методам без создания экземпляра объекта.
procedure TForm1.Button4Click(Sender: TObject);
var x:TMyClassC;
begin
form1.Edit2.Text:= TMyClassC.ClassName;
form1.Edit1.Text:=x.ClassName;
end;
Результат:
Рассмотрим оператор: form1.Edit1.Text:=x.ClassName;
При обращении к методу «ClassName» объект «x» ещё не создан. В этом случае обращение к методу класса через переменную возвращает тип того объекта, из которого вызван метод. Метод вызван из обработчика Button4Click, поэтому возвращается значение Tbutton.
Второй обработчик — обработчик клика по Edit1.
procedure TForm1.Edit1Click(Sender: TObject);
var x:TObject;
begin
form1.Edit3.Text:=x.ClassName;
end;
Метод вызван из обработчика Edit1Click, поэтому возвращается значение «Tedit».
Обращение к функции ClassName через класс TMyClassCвозвращает имя класса «TMyClassC».
Delphi конструктор класса
Однако надо помнить, что главной статической процедурой является конструктор Create.
Сама процедура Create ничего не делает (тело процедуры пустое), но служит основой для переопределения в потомках. Однако её вызов автоматически влечёт за собой вызов функции «_ClassCreate()». Внутри неё осуществляются ассемблеровские операции по распределению памяти под объект и вызов функции InitInstance.
В результате создаётся экземпляр объекта и возвращается указатель на него.
После создания объекта открывается доступ к его полям и нестатическим методам. Все поля инициируются нулевыми или пустыми значениями.
Если поле является ссылкой на объект, то ему присваивается значение nil.
Таким образом, основное предназначение статических методов TObject — создание экземпляра объекта.
Непосредственно к методам TObject как правило, не обращаются.
Экземпляр класса
Создавая переменную
var x:TObject;
и вызывая конструктор
x:=TObject .Create; //в переменную x записывается ссылка на созданный экземпляр объекта.
мы создаём экземпляр объекта и получаем доступ к его полям (либо напрямую, либо через свойства; о свойствах объекта речь пойдёт далее). Также мы получаем доступ не только к статическим, но также к динамическим и виртуальным методам.
Также мы получаем возможность наполнить содержанием методы, помеченные директивой «abstract»
После создания экземпляра объекта нам становится доступен весь список методов, полей и свойств экземпляра. В данном случае это методы объекта класса Tobject (полей у этого класса просто нет):