Форум: "Основная";
Текущий архив: 2003.07.10;
Скачать: [xml.tar.bz2];
Внизinherited inherited; Найти похожие ветки
← →
Um (2003-06-25 06:44) [0]Как можно вызвать inherited не у родителя а у дедушки.
Для примера
Задача такая: есть неплохой визуальный сторонний компонент.
Он наследован от Tcustomgrid,
в нем полностью переопределены MouseDown, KeyDown и т.д.
И ведет он себя не так как хотелось.
Надо чтобы управление было как в Tcustomgrid.
Как можно в MouseDown, KeyDown вернуться к Tcustomgrid?
← →
ЮЮ (2003-06-25 08:11) [1]1) Опять переопределить, поместив туда снова "дедушкин" код
2) закомментировать "отцовское" переопределение
← →
Um (2003-06-25 14:19) [2]1)
в "дедушкином" коде - вызывается inherited "прадедушки"
если переопределить то inherited будет "родителя"
2)
>закомментировать "отцовское" переопределение
в смысле исходним поправить - не выход, и не всегда возможно!
должен же быть способ вызвать виртуальный метод у нужного класса
типа TcustomGrid(mygrid).mousedown(...) причем mygrid другого типа
в таблице виртуальных методов есть адресса всех inherited методов, как найти адрес дедушки?
← →
Smithson (2003-06-25 14:50) [3]Короче, Склифософкий!
есть метод OnMouseOver, перекрытый у твоего класса. Ты знаешь, что инетерсующий тебя класс есть наследник класса TCustomGrid. Тогда пишешь наследник от интересующего тебя класса, у него перекрываешь метод OnMouseOver и в этом методе пишешь TCustomGrid.OnMouseOver.
Не запутался?
← →
uw (2003-06-25 16:27) [4]>Um (25.06.03 14:19)
>в таблице виртуальных методов есть адресса всех inherited методов, как найти адрес дедушки?
В VMT адрес метода внука лежит на месте адреса метода деда - не знает VMT ничего о дедовых методах. Когда мы зовем inherited, то компилятор осуществляет прямой вызов родительского метода, а не косвенный, хотя метод и виртуальный.
Но и TCustomGrid.OnMouseOver тоже не получится, это не BP. Все это неприятный прокол Delphi, imho.
← →
VMcL (2003-06-25 17:02) [5]>uw © (25.06.03 16:27)
>не знает VMT ничего о дедовых методах
Знает, в VMT есть ссылка на VMT родительского класса.
← →
VMcL (2003-06-25 17:19) [6]Привожу пример:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
end;
TGrandfather = class
procedure Test; virtual;
end;
TFather = class(TGrandfather)
procedure Test; override;
end;
TSon = class(TFather)
procedure Test; override;
procedure CallGrandTest;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
// AMethod - pointer to the method of such type: procedure XXX();
procedure CallMethod(const AObject, AMethod: Pointer); register;
asm
call edx
end;
{ TGrandfather }
procedure TGrandfather.Test;
begin
ShowMessage("Grandfather");
end;
{ TFather }
procedure TFather.Test;
begin
inherited;
ShowMessage("Father");
end;
{ TSon }
procedure TSon.CallGrandTest;
begin
CallMethod(Self, @TGrandfather.Test);
end;
procedure TSon.Test;
begin
ShowMessage("Son");
end;
procedure TForm1.FormCreate(Sender: TObject);
var
A: TSon;
begin
A := TSon.Create;
with A do
try
Test;
CallGrandTest;
finally
FreeAndNil(A);
end;
PostQuitMessage(0);
end;
end.
← →
reonid (2003-06-25 17:32) [7]type
TMouseDownProc = procedure (Button: TMouseButton;
Shift: TShiftState; X, Y: Integer) of object;
THackCustomGrid = class(TCustomGrid);
// метод MouseDown - protected
procedure TYourGrid.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
var
md: TMouseDownProc;
begin
// вызов непосредственно метода TCustomGrid.MouseDown
// для данного экземпляра
TMethod(md).Code := @THackCustomGrid.MouseDown;
TMethod(md).Data := Self;
md(Button, Shift, X, Y);
//...
end;
← →
VMcL (2003-06-25 17:47) [8]>reonid © (25.06.03 17:32)
Твой способ даже покрасивее :)
← →
Gamar (2003-06-25 17:56) [9]Да нельзя делать такие вещи. Это нарушает принцип наследование. Пишите наследника дедушки, а не его потомка.
← →
reonid (2003-06-25 18:06) [10]>Gamar © (25.06.03 17:56)
В старом турбопаскале, равно как и в современных Сях,
выполнение метода дедушки - вполне законная операция.
Иногда бывает полезна, хотя злоупотреблять не стоит.
Необходимость в ней может возникнуть, когда наследуешься от
чужих классов и перепроектировать их нет возможности.
← →
VMcL (2003-06-25 18:06) [11]>Gamar © (25.06.03 17:56)
>Да нельзя делать такие вещи.
Если бы было нельзя делать такие вещи, то код VMcL © (25.06.03 17:19) и код reonid © (25.06.03 17:32) не работали бы.
← →
uw (2003-06-25 19:38) [12]>VMcL © (25.06.03 17:19)
>reonid © (25.06.03 17:32)
Спасибо. Для меня было откровением, что синтаксис @TGrandfather.Test возможен. Но адрес все же берется не из VMT, а вычисляется компилятором точно так же, как и при inherited.
← →
Gamar (2003-06-25 19:43) [13]> VMcL
Вероятно, их код не стоит считать верхом совершенства...
← →
Serginio (2003-06-25 20:05) [14]Согласен с VMcL,reonid это самый простой и естественный способ.
Не согласен с Gamar так как на самом деле любой вызов метода объекта работает аналогично TMethod.
← →
Um (2003-06-26 06:47) [15]>VMcL
>reonid
Я когда прочитал - от радости на стуле подпрыгнул
SQL.ru - слабаки
delphimaster.ru - рулёзззз
← →
Um (2003-06-26 07:28) [16]Забыл, VMcL, Reonid, - большое спасибо!
>reonid
То-что доктор прописал - клёво!
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.07.10;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.007 c