Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Вызов 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


Наверх

Титульная страница Поиск, карта сайта Написать письмо