Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения
KANSoftWare

Как явно вызвать виртуальный метод дедушки?

Delphi , Технологии , Объектно-ориентированное программирование

Как явно вызвать виртуальный метод дедушки?

Проблема в следующем. Допустим, есть иерархия классов, у которых перекрывается один и тот же виртуальный (или динамический - не важно) метод и в одной из реализаций этого метода вы хотите вызвать виртуальный метод предка своего предка. Новая объектная модель Delphi допускает только вызов методов предка (с помощью ключевого слова inherited) либо вызов методов класса с префиксом - типом класса (например, TLevel1.ClassName).
 
Эта проблема стандартными средствами не решается. Но сделать требуемый вызов можно. Причем способом, показанным ниже, можно вызвать любой метод для любого класса, однако, в этом случае вся ответственность за правильность работы с методами и полями ложится на программиста. Ниже в методе VirtualFunction класса TLevel3 вызывается метод класса TLevel1, а в функции Level1Always всегда вызывается метод класса TLevel1 для любого его наследника.
 
Code:
 
TLevel1 = class(TComponent)
       public
        function VirtualFunction: string; virtual;
       end;
 
       TLevel2 = class(TLevel1)
       public
        function VirtualFunction: string; override;
       end;
 
       TLevel3 = class(TLevel2)
       public
        function VirtualFunction: string; override;
       end;
 
       function Level1Always(MyLevel: TLevel1): string;
 
implementation
 
       type
        PClass = ^TClass;
 
       function TLevel1.VirtualFunction: string;
       begin
        Result := 'Level1';
       end;
 
       function TLevel2.VirtualFunction: string;
       begin
        Result := inherited VirtualFunction+' Level2';
       end;
 
       function TLevel3.VirtualFunction: string;
       var
        ClassOld: TClass;
       begin
        ClassOld := PClass(Self)^;
        PClass(Self)^ := TLevel1;
        Result := VirtualFunction + ' Level3';
        PClass(Self)^ := ClassOld;
       end;
 
       function Level1Always(MyObject: TObject): string;
       var
        ClassOld: TClass;
       begin
        ClassOld := PClass(MyObject)^;
        PClass(MyObject)^ := TLevel1;
        Result := (MyObject as TLevel1).VirtualFunction;
        PClass(MyObject)^ := ClassOld;
       end;
 
Как же это работает? Стандартные так называемые объектные типы (object types - class of ...) на самом деле представляют из себя указатель на VMT (Virtual Method Table) - таблицу виртуальных методов, который (указатель) лежит по смещению 0 в экземпляре класса. Воспользовавшись этим, мы сначала сохраняем 'старый тип класса' - указатель на VMT, присваиваем ему указатель на VMT нужного класса, делаем вызов и восстанавливаем все как было. Причем нигде не требуется, чтобы один из этих классов был бы порожден от другого, т.е. функция Level1Always вызовет требуемый метод вообще для любого экземпляра любого класса.
 
Если в функции Level1Always сделать попробовать вызов
 
Code:
Result := MyObject.VirtualFunction;
 
 
то будет ошибка на стадии компиляции, так как у класса TObject нет метода VirtualFunction. Другой вызов
 
Code:
Result := (MyObject as TLevel3).VirtualFunction;
 
 
 
 
будет пропущен компилятором, но вызовет Run-time ошибку, даже если передается экземпляр класса TLevel3 или один из его потомком, так как информация о типе объекта меняется. Динамически распределяемые (dynamic) методы можно вызывать точно таким же образом, т.к. информация о них тоже хранится в VMT. Статические методы объектов вызываются гораздо более простым способом, например
 
Code:
var
        MyLevel3: TLevel3;
       ...
        (MyLevel3 as TLevel1).SomeMethode;
 
 
вызовет метод класса TLevel1 даже если у MyLevel3 есть свой такой же метод.
 
 
Copyright © 1996 Epsylon Technologies
Взято из FAQ Epsylon Technologies (495)-913-5608; (495)-913-2934; (495)-535-5349

Статья Как явно вызвать виртуальный метод дедушки? раздела Технологии Объектно-ориентированное программирование может быть полезна для разработчиков на Delphi и FreePascal.


Комментарии и вопросы


Ваше мнение или вопрос к статье в виде простого текста (Tag <a href=... Disabled). Все комментарии модерируются, модератор оставляет за собой право удалить непонравившейся ему комментарий.

заголовок

e-mail

Ваше имя

Сообщение

Введите код




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: Объектно-ориентированное программирование ::


реклама



©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru Rambler's Top100
23.04.2024 11:04:16/0.0045230388641357/2