![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Вызов inherited определённого базового класса
LightGreen © (2010-02-09 12:42:00)Такой вот вопрос... Есть иерархия классов A : B : C.
Я хочу из C вызвать метод foo(), реализованный в A.
Если я напишу inherited, то вызовется метод из B.
На C++ это делается просто A::foo(). А как это сделать в Delphi?
Спасибо.
GrayFace (2010-02-18 20:53:00) [1]Тогда так:
procedure TC.Foo;
type
TObjectProcedure = procedure of object;
var
M: TObjectProcedure;
class: TClass;
begin
class:= PClass(Obj)^;
PClass(Obj)^:= TA;
M:= Foo;
PClass(Obj)^:= class;
M(); // вызов производится уже с правильной ссылкой на VMT
end;
icWasya (2010-02-17 17:26:00) [2]to LightGreen (11.02.10 13:53) [11]
> Тем более, что в C++ это делается элементарно ?
А вот так http://rsdn.ru/forum/cpp/3705754.1.aspx
Юрий Зотов (2010-02-17 15:45:00) [3]> LightGreen (11.02.10 13:53) [11]
> использовать присвоение PClass(Obj) на время вызова.
Временная подмена ссылки на класс. Это стандарный способ вызова метода удаленного предка (да и не только предка) - но не забудьте использовать try-finally, иначе можно нахватать глюков по самое некуда.
KSergey (2010-02-11 17:20:00) [4]> jack128_ (09.02.10 18:13) [9]
Зачем плохому учишь? :)
LightGreen (2010-02-11 13:53:00) [5]Спасибо. Правда метод с TObjectProcedure работает только для public методов. Уже нашёл, как сделать для других - использовать присвоение PClass(Obj) на время вызова.
Для int64 - такие ситуации не обязательно связаны с кривым дизайном. Если используется код от разных поставщиков и менять в нём ничего нельзя, а можно только наследоваться, то этот приём может понадобиться. Тем более, что в C++ это делается элементарно. И ещё - если я вообще не вызову inherited - это тоже может что-то сломать, но язык позволяет беспрепятственно.
Ещё раз спасибо всем, кто откликнулся.
int64 (2010-02-10 16:38:00) [6]LightGreen (09.02.10 12:42)
Много раз уже писалось, что необходимость сабжа:
1. (в большенстве случаев) связяна с кривой разработкой классов;
2. (в остальных случаях) можно обойтись без сабжа.
jack128_ (2010-02-09 18:13:00) [7]
> LightGreen (09.02.10 12:42)
для НЕвируальных методов - TA(Self).Foo();
для виртуальных/димамических так просто не получится:
type
TA = class
public
procedure Foo(); dynamic;
end;
TAClass = class of TA;
TB = class(TA)
public
procedure Foo(); override;
end;
TC = class(TB)
public
procedure Foo(); override;
end;
procedure TA.Foo;
begin
ShowMessage('A');
end;
procedure TB.Foo;
begin
ShowMessage('B');
end;
procedure TC.Foo;
type
TObjectProcedure = procedure of object;
var
M: TMethod;
begin
M.Code := @TA.Foo;
M.Data := Self;
TObjectProcedure(M)();
end;
procedure TForm2.Button1Click(Sender: TObject);
begin
with TC.Create do
try
Foo;
finally
Free;
end;
end;
Ega23 (2010-02-09 15:18:00) [8]
TA = class
protected
procedure Foo;
end;
TB = class (TA)
protected
procedure Foo;
end;
TC = class (TB)
protected
procedure Foo;
public
procedure AFoo;
procedure BFoo;
procedure CFoo;
end;
{ TA }
procedure TA.Foo;
begin
ShowMessage('TA.Foo;');
end;
{ TB }
procedure TB.Foo;
begin
ShowMessage('TB.Foo;');
end;
{ TC }
procedure TC.AFoo;
begin
TA(Self).Foo;
end;
procedure TC.BFoo;
begin
inherited Foo;
end;
procedure TC.CFoo;
begin
Foo;
end;
procedure TC.Foo;
begin
ShowMessage('TC.Foo;');
end;
procedure TForm1.Button2Click(Sender: TObject);
var
t : TC;
begin
t := TC.Create;
try
t.AFoo;
t.BFoo;
t.CFoo;
finally
t.Free;
end;
end;
Ega23 (2010-02-09 15:17:00) [9]
> webpauk © (09.02.10 15:13) [5]
> stack overflow
Немудрено. Обезьяна с гранатой - страшное дело.
Совет читать книги продолжает быть актуальным.
webpauk (2010-02-09 15:13:00) [10]
> Ega23 © (09.02.10 15:10) [2]
>
stack overflow
webpauk (2010-02-09 15:13:00) [11]исправление:
class procedure TC.Show;
begin
TA.Show;
end;
webpauk (2010-02-09 15:12:00) [12]TA = class
public
class procedure Foo(); dynamic;
end;
TB = class(TA)
public
class procedure Foo(); override;
end;
TC = class(TB)
public
class procedure Foo(); override;
end;
class procedure TA.Show;
begin
ShowMessage('A');
end;
class procedure TB.Show;
begin
ShowMessage('B');
end;
class procedure TC.Show;
begin
TA(Self).Show;
end;
Ega23 (2010-02-09 15:11:00) [13]
> только условие: процедура A.foo() должна быть объявлена
> в разделе public как class procedure.
> соотв. и в классе B, и в классе С
Эта... Иди книжки читай умные.
webpauk (2010-02-09 15:10:00) [14]а ты не пиши inherited.
пиши A.foo()
только условие: процедура A.foo() должна быть объявлена в разделе public как class procedure.
соотв. и в классе B, и в классе С
Ega23 (2010-02-09 15:10:00) [15]
A(Self).Foo