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

Var ObjRef: tObjRef;

S: String;

Begin

ObjRefs^TMyClass; // Ссылка на класс, а не на экземпляр

S:=ObjRef.ClassName; // Строка S содержит строку "IMyClass'

. . .

S:=Sender.ClassName; // Строка S содержит имя класса

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

Type

TMyControl=Class OfTControl;

. . .

Implementation

Function MyCreate(MyClass: TMyControl; Const MyName: String;

X, y, w, h: Integer): tControl;

Begin

// Создаем новый объект, класс которого MyClass

Result:=MyClass.Create(Forml);

With Result Do Begin

Parent:=Fonnl; // Parent: =Forml.Panell; - на другом контейнере

Name:=MyName;

SetBounds(X. Y, W, H);

Visible:=True;

End;

End;

Begin

// Создание поля ввода в нужном месте производится следующим образом

MyCreate(TEdit, 'Editi', 10,10,100,20);

Для динамического удаления компонентов можно воспользоваться свойствами ComponentCount и Components [Index] и оператором Is или ис­пользовать функцию FindComponent.

For I:=0 To ComponentCount-l Do

lfComponents[I| Is TEdit Then Components|I].Free;

FindComponent('Editl').Free;

FindComponent(TControl(Sender).Name).Free;

Фактически Delphi использует виртуальный конструктор, создавая ком­поненты на форме после вашего щелчка по компоненту на палитре компо­нентов и форме.

5. Полиморфизм

Полиморфизм (или много форм) - третья и самая мощная грань ООП. Полиморфизм может быть описан как поведенческая абстракция, - возмож­ность вызывать действие или поведение по имени какого-либо конкретного экземпляра класса, не зная в точности, какая именно реализация метода при этом будет вызвана, и даже не зная в точности, к какому типу принадлежит данный объект. Тип экземпляра класса и реализация метода, который будет вызван в процессе выполнения программы, не могут быть полностью опреде­лены на фазе трансляции. Более того, процесс будет выполняться динамиче­ски - один и тот же код может работать с экземплярами разных классов.

Ключевой момент в виртуальных методах - указатели на код, хранящий­ся в VMT, а ключевой момент в полиморфизме - использование данных экземпляра класса для получения указателя на нужную таблицу VMT во время выполнения программы. Действительно, у компилятора нет возможности оп­ределить класс объекта, фактически передаваемого для обработки в процессе выполнения программы. Поэтому нужен механизм, позволяющий определить это непосредственно во время выполнения, - это называется поздним связы­ванием (late binding). Этот механизм должен быть связан с передаваемым объектом. В качестве такого механизма и служат VMT и DMT.

Таким образом, полиморфизм - это механизм, позволяющий во время

работы программы установить родительский объект равным одному из до­черних.

Для реализации полиморфизма подходят две схемы взаимоотношения класса-предшественника и производного класса:

• есть класс-предшественник, в котором объявлен один или более вир­туальных (динамических) методов. Имеется производный класс, в котором

произведено замещение одного или более виртуальных (динамических) мето­дов класса-предшественника;

• есть класс-предшественник, в котором объявлен один или более абст­рактных метода. Имеется один или более производных класса, в которых пе­реопределены абстрактный метода класса-предшественника.

Экземпляр производного класса можно присвоить переменной класса-предшественника, но обратное невыполнимо, поскольку объект производного класса больше объекта класса-предшественника, поскольку включает новые поля и/или методы. Более того, если бы это было возможно, то экземпляр класса-предшественника мог бы обращаться к полям и методам, которых у него нет.

Таким образом, полиморфизм возможен тогда, когда имеется:

• класс предшественник, определяющий один или более виртуальных методов;

• один или более производных классов, которые могут замещать эти виртуальные методы;

• переменная представителя класса, объявленная, как переменная типа класса-предшественника, но реально содержащая представителя одного из производных классов.

Type

TBaseClass=CIass // Базовый класс

FDate: TDateTime;

Function GetDate: String; Virtual; Abstract;

End;

TDateCIass=Class(TBaseClass) // Первый производный класс

Function GetDate: String; Override;

End;

TTimeCIass=Class(TBaseClass) // Второй производный класс

Function GetDate: String; Override;

• В обработчиках событий OnClick всех указанных компонентов указать FormClick.

• После запуска формы можно щелкнуть по любому компоненту, и бу­дет происходить его перемещение в другое место (или перерисовка -Repaint), которое для каждого из них будет происходить известным для него способом, иначе все компоненты были бы одинаковыми.

Если в этом примере заменить исполняемый код на:

(Sender As TControl).Hint:='Это ярлычок!';

и установить свойство ShowHint экранной формы в True, то после щелч­ка мышью по форме ярлычки будут далее появляться у всех компонентов. Это пример полиморфного присвоения. Щелчок по компоненту приводит к появлению подсказки у него.

Поскольку все используемые компоненты являются потомками от TControl, они обрабатываются одинаково, т.е. всем присваивается одинаковое значение.

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

У каждого классового типа есть своя уникальная VMT (DMT). Блок дан­ных экземпляра каждого типа содержит скрытый указатель на VMT своего класса (напомним, что VMT - это принадлежность класса, а не экземпляра или объекта). Когда транслятору нужно сгенерировать код для вызова вирту­ального метода, он сначала генерирует код для получения указателя на VMT из данных экземпляра, затем получает адрес кода нужного метода из соответ­ствующего поля VMT и далее выполняется вызов по полученному адресу.

Полиморфизм использует абстракцию и помогает ей, используя обоб­щенные процессы для управления родственными специализированными ре­акциями. За счет малого количества кода контролируется обширный набор вариантов поведения.