Методы virtual и полиморфизм
Особенности виртуальных (Virtual) методов рассмотрим на примере. Пусть объявлен класс AClass. Этот класс имеет потомка, который, в свою очередь, также имеет потомка, например, AClass ® BClass ® CClass.
Пусть AClass содержит метод Drag, который служит для рисования некоторой геометрической фигуры. При этом внутри метода Drag вызывается метод Show для рисования заданной фигуры. Пусть метод Showреализован в каждом из трёх указанных классов для рисования точки (класс AClass), окружности (BClass) и квадрата (CClass).Метод Drag содержится только в AClass. Так как нужная фигура вызывается для рисования из метода Show, нет необходимости дублировать его в других классах. Пусть заданы три объекта:
Var A:AClass; B:Bclass; C:Cclass;
Пусть с помощью соответствующих конструкторов эти объекты созданы. Пусть вначале все три метода Show объявлены как статические. Запишем вызов на рисование геометрической фигуры: C.Drag;
Рассмотрим, какая фигура изобразится в данном случае. По линии наследования от CСlass, вызвавшего Drag, в классе AClass найдётся метод Drag. При вызове происходит обращение к Show. В данном случае вызовется ближайший к Drag метод, находящийся в классе AClass, т.е. изобразится точка. Вызвать метод Show из класса BClass для рисования окружности или вызвать Show из CClass и нарисовать квадрат с помощью статических методов Show нельзя.
Итак, в данном случае ставится следующая задача. Вызов C.Drag; должен нарисовать квадрат, B.Drag; - окружность, соответственно A.Drag; - точку, т.е. C.Dragдолжен вызвать Showиз класса CClass, B.Dragдолжен вызвать Show из класса BClass, а A.Drag - Show из класса AClass. Такая задача решается с помощью виртуальных методов Show. Тогда вызов Show будет определяться конкретным фактическим объектом.
Виртуальные методы определяются с помощью ключевого слова Virtual. По линии наследования все реализации одного и того же виртуального метода должны иметь одинаковые заголовки. С помощью зарезервированного слова Virtual определяется самая первая реализация виртуального метода, все последующие реализации переопределяются с помощью ключевого слова Override. Если заданный метод появляется далее по линии наследования без ключевого слова Override, то свойство виртуальности теряется для данного класса и всех его потомков.
Статические методы определяются на этапе компиляции, а виртуальные – при выполнении программы. Для реализации вызовов виртуальных методов в зависимости от фактического объекта строится так называемая таблица виртуальных методов. Построение этой таблицы возлагается на соответствующий конструктор.
Свойство одного и того же метода вести себя по-разному называется полиморфизмом (многоформным). Например, метод Drag, указанный в примере выше, может построить точку, окружность или квадрат. Для реализации полиморфизма используются виртуальные методы.
Итак, наряду с инкапсуляцией и наследованием, третьей особенностью типа класс по сравнению с другими типами является полиморфизм.
МЕТОДЫ DYNAMIC
Механизм Dynamic доступа к другим методам подобен механизму Virtual. В обоих случаях адрес нужной процедуры или функции определяется фактическим объектом. Отличие заключается в том, что в данном случае строится таблица динамических методов. Обращение к этой таблице происходит медленнее, чем к таблице виртуальных методов, зато объём программы получается меньше. Методы Dynamic целесообразно использовать, когда класс имеет множество потомков, а количество переопределяемых методов небольшое.
МЕТОДЫ MESSAGE
Методы Message - обработки сообщений - представляют собой особую форму динамических методов. Обработчики сообщений всегда являются процедурами. Для ускорения поиска в таблице динамических методов после ключевого слова Message записывается константа целого типа, являющаяся индексом нужного метода. В обработчике сообщений всегда имеется один параметр Var. Методы Message – это одно из звеньев взаимодействия компонентов Delphi с Windows.
Объявление обработчика сообщений выглядит приблизительно так: Procedure Handle_WM_Paint(var MsgInfo);Message WM_Paint;
Для поиска нужного адреса в таблице динамических методов в данном примере записана константа WM_Paint. Многие константы для Message зарезервированы за конкретными сообщениями Windows и выбирать их произвольно нельзя. Указанная константа поиска данного сообщения Windows может быть переопределена в каком-либо предке по линии наследования для данного объекта. Если константа Message не найдена, то вызывается метод обработки сообщений, заданный по умолчанию.
МЕТОДЫ ABSTRACT
Обычно методы создаются для выполнения каких-то конкретных действий. Если по какой-либо причине это выполнить не удаётся, метод в классе может быть зарезервирован с обязательным переопределением его в классах потомков. Такой метод помечается ключевым словом Abstract. Если абстрактный метод не переопределён, то вызов такого метода приводит к вызову специальной процедуры Abstract, которая генерирует исключительную ситуацию. Абстрактным не может быть статический метод, так как статические методы нельзя переопределять. Например, Type TmyParent=class
Procedure AMethod;virtual;abstract;
End;
TmyClass=class(TmyParent)
Procedure AMethod;override;
End;
МЕТОДЫ OVERRIDE
Как указано выше, зарезервированным словом Overrideпомечаются переопределённые виртуальные или динамические методы (пример выше).
МЕТОДЫ CLASS
Исходное назначение методов – определять поведение экземпляров объектов какого-либо класса. В некоторых случаях необходимо иметь ситуацию, когда поведение, задаваемое для метода, не должно зависеть от реально существующего объекта. Такая ситуация возникает с методом, который, например, должен возвращать имя класса. В этом случае метод помечается ключевым словом Class. В отличие от других команд, таких как Dynamic, Virtual и т.д., слово Class ставится перед заголовком метода, например, Class Procedure AMethod;.
ПРИМЕР 14
Рассмотрим пример по использованию конструкторов и деструкторов в объектах. Кроме того, посмотрим, как можно использовать указатели на методы и методы class.
Пусть на форме дирамически строится совокупность объектов типа TButton. Далее, пусть эти объекты последовательно разрушаются с выдачей соответствующих сообщений о количестве объектов. Рассматривать этот пример будем последовательно, вводя все новые и новые конструкции и проверяя их непосредственно в среде Delphi.