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

10.2. Виртуальные методы

Часто производные объектные типы на основе некоторого базового типа создаются другими программистами. Автор базового типа не может знать заранее, подойдут ли его реализации методов всем желающим. А вдруг кому-то понадобится моделировать не автомобиль с двигателем внутреннего сгорания, а трамвай, у которого тоже есть почти все свойства автомобиля, но процедура запуска двигателя совершенно другая?

В таком случае создатель базового метода может немного схитрить, облегчив работу и себе, и людям. Не нравится вам моя реализация метода "Начало движения" – пишите свою, пусть она перекроет то, что написал я.

Методы, которые можно перекрыть одноименными методами объектов-потомков, называются виртуальными (Рис. 10 .22).

Рис. 10.22. Виртуальные методы.

Например:

TYPE Tcar=CLASS PROCEDURE Move; VIRTUAL; { этот метод можно перекрыть } END; … TYPE Ttruck=CLASS(Tcar) PROCEDURE Move; OVERRIDE; { перекрытие метода Move } END;

А вот в производном объекте для перекрытия одноименного виртуального метода нужно указать слово OVERRIDE (перекрыть). Тогда при выполнении следующего фрагмента программы:

VAR Car:Ttruck; … Car:=TTruck.Create; Car.Move

будет вызван метод Move объекта Ttruck – в полном соответствии в принципом полиморфизма.

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

Методы, не имеющие реализации, называются абстрактными. Поскольку абстрактный метод обязательно должен перекрываться настоящим (с реализацией) методом в объекте-потомке, все абстрактные методы должны одновременно быть и виртуальными. Записывается это так:

TYPE Tcar=CLASS PROCEDURE Move;VIRTUAL;ABSTRACT; END;

Реализации метода Tcar.Move в программе вообще нет. Соответственно, и вызвать на исполнение абстрактный метод в базовом объекте нельзя – исполнять-то нечего! Следующая запись вызовет ошибку:

VAR c:Tcar; c:=TCar.Create;

c.Move

Особым случаем применения виртуальных методов следует считать их использование в конструкторе объекта. При создании любого объекта в Delphi, если родитель объекта явно не указан, он считается потомком некоего виртуального объектного типа Tobject. Следующие фрагменты программы эквивалентны:

TYPE TA=CLASS

и

TYPE TA=CLASS(TObject)

Если объект не требует какой-то специфической инициализации, то при создании переменной-объекта достаточно вызвать метод Create, унаследованный от объекта Tobject. Иначе обстоит дело при написании своего собственного конструктора. Рассмотрим пример:

TYPE TA=CLASS

a:BYTE;

CONSTRUCTOR Create;

END;

VAR aa:TA;

constructor TA.Create(x:byte);

begin

inherited Create;

self.a:=x

end;

В объекте TA создан метод-конструктор с именем Create, который перекрывает одноименный метод родительского объекта TObject. Однако именно метод родительского объекта вызывать следует обязательно: он выделяет память под объект. Поэтому в теле процедуры-конструктора оператором INHERITED сразу вызывается метод Create объекта-родителя. После выполнения родительского метода объект становится проинициализированным и можно задавать начальные значения его свойств.