Application.CreateForm(TForml, Fonnl);

и) Динамическое создание объектов. Пользователь может создать объект и программным путем:

Var Mem: TMemo;

Begin

Mem:=TMemo.Create(Self); // Создание экземпляра класса TMemo

Mem.Parent:=Self; // Form1 указывать не обязательно

Mem.Name:='TmpMem'; // Присвоение имени компоненту

FindComponent('TmpMem').Free; // Удаление компонента

Классовые процедуры и функции

Наиболее важное отличие классовых методов от обычных заключается в том, что при их вызове не требуется экземпляр класса, вследствие чего не­возможно и обращение к его полям. Классовые методы - это обычные под­программы.

а) Синтаксис объявления классовых методов:

Type <имя клacca>=Class[(<имя родительского класса>)]

. . .

Class Procedure <имя процедуры>[(<параметры>)};

Class Function <имя функции>[(<параметры>)]:<тип результата>

. . .

End;

Примечания:

- В классе может быть объявлено несколько классовых методов.

- Каждое объявление классового метода должно начинаться с зарезер­вированного словаClass, за которым следует объявление процедуры или функций по обычным правилам.

- Фактически классовые методы ничем не отличаются от обычных процедур и функций. Классовые методы - это лишь удобная возможность указать, что данный метод логически относится к данному классу.

- Реализация классового метода не должна зависеть от состояния лю­бого поля класса во время выполнения. Поля экземпляра класса недоступны для этих методов.

- Классовые методы могут быть виртуальными, при этом их можно переопределять и использовать полиморфизм.

- Одно из назначений классовых методов заключается в возможности извлечения данных о классе из структуры RTTI. Важнейшие из них определе­ны в самом классе TObject: имя класса (ClassName), размер экземпляра (InstanceSize), адреса (MethodAddress) и имена методов (MethodName), ука­затель на класс-предок (ClassParent) и указатель (Classlnfo) на структуру PTypelnfo, позволяющую извлекать всю информацию о классе из структуры (RTTI) и другие.

Var S: String;

Begin

S:=TCoIorLine.Cla»sParent.ClassNanie; // S содержит TLine S:=ALine.ClassName; // S содержит TLine

Наибольшие возможности заложены в функции Classlnfo, для обслужи­вания которой в Delphi предусмотрен целый блок Typlnfo, включающий большой набор методов, позволяющих манипулировать информацией о ти­пах объектов, типах свойств объектов, типах указателей на методы, при­сваивать значения свойствам объектов. Следует только иметь в виду, что подробная информация для RTTI генерируется для раздела Published потом­ков класса TPersistent. Примеры использования этой функции имеются в ис­точниках, приведенных в списке литературы.

б) Реализация классовых методов.

Реализация классового метода достаточно проста. Основное отличие за­ключается в том, что реализация должна начинаться с зарезервированного слова Class.

Синтаксис реализации классовых методов следующий:

Class Procedure <имя класса>.<имя процедуры>[(<параметры>)];

[<блок объявлений>]

Begin

<Исполняемые операторы>

End;

Class Function <имя класса>.<имя функции>[(<параметры>)]:

<тип результатам, [<блок обьявлений>]

Begin

<Исполняемые операторы>

Result:'=<возвращаемое значение>;

<Исполняемые операторы>

End;

Примечания:

- Как всегда в теле функции должен быть хотя бы один оператор, при­сваивающий идентификатору функции либо предопределенной переменной Result возвращаемое значение.

- Важно помнить, что внутри классового метода нет доступа к полям экземпляра класса.

в) Вызов классовых методов. Классовые методы могут быть вызваны несколькими способами:

- с использованием имени класса:

<имя класса>.<имя классового метода>[{<параметры>}];

- через экземпляр класса, т.е. как обычный метод, а именно:

<имя объекта>.<имя классового метода>[(<параметры>)];

- классовые методы могут также вызываться с помощью переменной' типа указателя на класс.

Скрытый Self

Между самостоятельными подпрограммами и методами, исключая клас­совые, имеется существенное отличие, которое состоит в способе доступа к данным экземпляра класса.

Как известно, для того, чтобы самостоятельные подпрограммы могли работать с элементами данных, эти данные должны быть переданы подпро­граммам, предпочтительно в виде параметров. Кроме того, самостоятельные подпрограммы имеют доступ к любым данным, объявленным глобально в модуле или программе, а также ко всем глобальным переменным других мо­дулей, перечисленных в списке секции Uses.

Методы, исключая классовые, имеют, помимо этого, неявный доступ к полям того экземпляра класса, который был использован при их вызове. Это происходит потому, что фактически при вызове в каждый метод передается дополнительный параметр -указатель на использовавшийся при вызове ме­тода объект, а внутри метода стоит неявный оператор With, заключающий в себе все тело метода. Этот неявный параметр (предопределенный идентификатор) называетсяSelf, и он имеет тот же тип. что и класс, в котором опреде­лен метод.

Все тело метода заключено в неявный операторWith SelfDo, который предоставляет методу доступ к полям, свойствам и другим методам данного объекта. Поскольку параметр Self неявно присутствует внутри метода, то в большинстве случаев не будет возникать необходимости в его явном исполь­зовании. Его явное использование может понадобиться, например, для раз­решения конфликтов идентификаторов внутри метода, когда имя локальной переменной совпадает с именем поля. Тогда для обращения к полю, напри­мер, FTitle следует указать Self.FTitle.

Параметр Self часто используется, когда требуется обратиться к текущей форме в одном из ее методов. Типичный пример - динамическое создание компонента, когда нужно передать параметр Owner (т.е. указать владельца) конструктору Create. Например, по щелчку мыши по форме (событие OnMouseDown) или даже по щелчку по другой кнопке (событие OnClick) можно создать кнопку.