Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2011-01

Skipping an the "inherited" of an ancestor

10 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Torsten Bonde Christiansen

Hi List.

Is it possible to jump a couple of levels in the inherited hierarchy when calling "inherited" on a method?

A small example of what i'm trying to achieve below (and don't mind the incomplete TB class implementation).

Kind regards,
Torsten Bonde Christiansen.

============================

TA = class
   procedure DoSomething; virtual;
end;
TB = class(TA)
   procedure DoSomething; override;
end;
TC = class(TB)
   procedure DoSomething; override;
end;

.....

procedure TA.DoSomething;
begin
   ...
end;
procedure TC.DoSomething;
begin
   inherited TA.DoSomething;  // This is not correct, but exemplifies
what i'm trying to achieve.
end;
Max Vlasov
to Torsten Bonde Christiansen
Torsten Bonde Christiansen wrote 6 lines
Hi List. Is it possible to jump a couple of levels in the inherited hierarchy when calling "inherited" on a method?

Hmm, don't know whether you're the same person or not :), but I replied in a stackoverflow question the next day after it was asked (see here: http://stackoverflow.com/questions/4662744/delphi-how-to-call-inherited-inherited-ancestor/4670457#4670457) and it looked like the host didn't notice :). At least this variant seemed
to work

code is self-explanatory

type
  TGrandParent = class(TObject)
  public
    procedure Show;virtual;
  end;
  TParent = class(TGrandParent)
  public
    procedure Show;override;
  end;
  THackParent = class(TGrandParent)
  private
    procedure CallInheritedShow;
  end;
  TMyObject = class(TParent)
  public
    procedure Show;override;
  end;

{ TGrandParent }

procedure TGrandParent.Show;
begin
  MessageDlg('I''m the grandparent', mtInformation, [mbOk], 0);
end;

{ TParent }

procedure TParent.Show;
begin
  inherited;
  MessageDlg('I''m the parent', mtInformation, [mbOk], 0);
end;

{ THackParent }

procedure THackParent.CallInheritedShow;
begin
  inherited Show;
end;

{ TMyObject }

procedure TMyObject.Show;
begin
  THackParent(Self).CallInheritedShow;
end;
procedure TForm6.Button6Click(Sender: TObject);
var
  Obj: TMyObject;
begin
  Obj:=TMyObject.Create;
  try
    Obj.Show;
  finally
    Obj.Free;
  end;
end;
+

Max

Torsten Bonde Christiansen
to Max Vlasov
Max Vlasov wrote 17 lines
On Fri, Jan 14, 2011 at 10:38 PM, Torsten Bonde Christiansen < > wrote: Hi List. Is it possible to jump a couple of levels in the inherited hierarchy when calling "inherited" on a method? Hmm, don't know whether you're the same person or not :), but I replied in a stackoverflow question the next day after it was asked (see here: http://stackoverflow.com/questions/4662744/delphi-how-to-call-inherited-inherited-ancestor/4670457#4670457 ) and it looked like the host didn't notice :). At least this variant seemed to work

I'm sorry to say that it is not I who wrote on stackoverflow, but could as well have been. Anyways, your solution does not really solve the problem, since i will have to introduce a HackedParent class and that kinds of defeat the purpose.
All I really want is to skip to a grandparent class using the normal "inherited" functionality. I have tried to look through the mailinglist archive, because I seem to remember someone else might have asked this question as well - but I haven't been able to find anything (yet).

Kind regards,
Torsten Bonde Christiansen.

Max Vlasov
to Torsten Bonde Christiansen
Torsten Bonde Christiansen wrote 24 lines
On 2011-01-14 23:05, Max Vlasov wrote: On Fri, Jan 14, 2011 at 10:38 PM, Torsten Bonde Christiansen < > wrote: > Hi List. > > Is it possible to jump a couple of levels in the inherited hierarchy when > calling "inherited" on a method? > > Hmm, don't know whether you're the same person or not :), but I replied in a stackoverflow question the next day after it was asked (see here: http://stackoverflow.com/questions/4662744/delphi-how-to-call-inherited-inherited-ancestor/4670457#4670457) and it looked like the host didn't notice :). At least this variant seemed to work I'm sorry to say that it is not I who wrote on stackoverflow, but could as well have been. Anyways, your solution does not really solve the problem, since i will have to introduce a HackedParent class and that kinds of defeat the purpose.

Torsten, the problem is that such purpose itself is a bit strange for OOP. Imagine some of ancestors call some other virtual method inside the procedure you need to call, and this method was overridden by your skipped ancestor, in this case you have uncontrolled functionality of one of the levels of hierarchy you want to skip. There's no way to control intermediate ancestor completely so any possible solutions will be a kind of a hack.

Max

Martin
to Torsten Bonde Christiansen: I'm sorry to say that it is not I who wrote on stackoverflow, but could as well have…
Torsten Bonde Christiansen wrote 21 lines
> > Is it possible to jump a couple of levels in the inherited > hierarchy when calling "inherited" on a method? > > > Hmm, don't know whether you're the same person or not :), but I > replied in a stackoverflow question the next day after it was asked > (see here: > http://stackoverflow.com/questions/4662744/delphi-how-to-call-inherited-inherited-ancestor/4670457#4670457 > ) and it looked like the host didn't notice :). At least this variant > seemed to work I'm sorry to say that it is not I who wrote on stackoverflow, but could as well have been. Anyways, your solution does not really solve the problem, since i will have to introduce a HackedParent class and that kinds of defeat the purpose. All I really want is to skip to a grandparent class using the normal "inherited" functionality. I have tried to look through the mailinglist archive, because I seem to remember someone else might have asked this question as well - but I haven't been able to find anything (yet).

Here is another "solution" (another hack):

program Project1;
{$mode objfpc}{$H+}
type
   { TFoo }
   TFoo = class
   protected
     procedure DoHello; virtual;
   end;
   { TFooChild }
   TFooChild = class(TFoo)
   protected
   end;
   { TFooGrandChild }
   TFooGrandChild = class(TFooChild)
   protected
     procedure DoHello; override; // to be skipped
   end;
   { TFooGreatGrandChild }
   TFooGreatGrandChild = class(TFooGrandChild)
   protected
     procedure DoHello; override;
   end;

{ TFoo }

procedure TFoo.DoHello;
begin
   writeln('TFoo');
end;

{ TFooGrandChild }

procedure TFooGrandChild.DoHello;
begin
   writeln('TFooGrandChild');
   inherited DoHello;
end;

{ TFooGreatGrandChild }

procedure TFooGreatGrandChild.DoHello;
var
   a: procedure of object;
begin
   writeln('TFooGreatGrandChild');
   //inherited DoHello;
   TMethod(a).Code := @TFooChild.DoHello;
   TMethod(a).Data:= Self;
   a();
end;
var
   a: TFoo;
begin
   a := TFooGreatGrandChild.Create;
   a.DoHello;
   readln;
end.
Andrew Haines
to Torsten Bonde Christiansen: Hi List. Is it possible to jump a couple of levels in the inherited hierarchy when…
Torsten Bonde Christiansen wrote 38 lines
Hi List. Is it possible to jump a couple of levels in the inherited hierarchy when calling "inherited" on a method? A small example of what i'm trying to achieve below (and don't mind the incomplete TB class implementation). Kind regards, Torsten Bonde Christiansen. ============================ TA = class procedure DoSomething; virtual; end; TB = class(TA) procedure DoSomething; override; end; TC = class(TB) procedure DoSomething; override; end; ..... procedure TA.DoSomething; begin ... end; procedure TC.DoSomething; begin inherited TA.DoSomething; // This is not correct, but exemplifies what i'm trying to achieve. end;

I *think* I've done this before this way but test it to make sure it works:

procedure TC.DoSomething:
begin
 (Self as TA).DoSomething;
end;

Regards,

Andrew

Jorge Aldo G. de F. Junior
to Andrew Haines

does inherited inherited work ?

as in

procedure TD.DoSomething;
Begin
  Inherited Inherited DoOtherthing;
End;

2011/1/15 Andrew Haines :

Show quoted text 54 lines
On 01/14/11 14:38, Torsten Bonde Christiansen wrote: > Hi List. > > Is it possible to jump a couple of levels in the inherited hierarchy > when calling "inherited" on a method? > > A small example of what i'm trying to achieve below (and don't mind the > incomplete TB class implementation). > > Kind regards, > Torsten Bonde Christiansen. > > ============================ > > TA = class >   procedure DoSomething; virtual; > end; > > TB = class(TA) >   procedure DoSomething; override; > end; > > TC = class(TB) >   procedure DoSomething; override; > end; > > ..... > > procedure TA.DoSomething; > begin >   ... > end; > > procedure TC.DoSomething; > begin >   inherited TA.DoSomething;  // This is not correct, but exemplifies > what i'm trying to achieve. > end; > I *think* I've done this before this way but test it to make sure it works: procedure TC.DoSomething: begin  (Self as TA).DoSomething; end; Regards, Andrew _______________________________________________ fpc-pascal maillist  -   http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Max Vlasov
to Andrew Haines: I *think* I've done this before this way but test it to make sure it works: procedure…
Andrew Haines wrote 48 lines
On 01/14/11 14:38, Torsten Bonde Christiansen wrote: > Hi List. > > Is it possible to jump a couple of levels in the inherited hierarchy > when calling "inherited" on a method? > > A small example of what i'm trying to achieve below (and don't mind the > incomplete TB class implementation). > > Kind regards, > Torsten Bonde Christiansen. > > ============================ > > TA = class > procedure DoSomething; virtual; > end; > > TB = class(TA) > procedure DoSomething; override; > end; > > TC = class(TB) > procedure DoSomething; override; > end; > > ..... > > procedure TA.DoSomething; > begin > ... > end; > > procedure TC.DoSomething; > begin > inherited TA.DoSomething; // This is not correct, but exemplifies > what i'm trying to achieve. > end; > I *think* I've done this before this way but test it to make sure it works: procedure TC.DoSomething: begin (Self as TA).DoSomething; end;

The same vmt (virtual method table) used, so no matter how you call it, the addresses point to new methods.

Max

Andrew Haines
to Andrew Haines: I *think* I've done this before this way but test it to make sure it works: procedure…
Andrew Haines wrote 15 lines
On 01/14/11 14:38, Torsten Bonde Christiansen wrote: > Hi List. > > Is it possible to jump a couple of levels in the inherited hierarchy > when calling "inherited" on a method? > > I *think* I've done this before this way but test it to make sure it works: procedure TC.DoSomething: begin (Self as TA).DoSomething; end;

Okay I tested that and it didn't work.

Does TC.DoSomething do anything other than call inherited from TA? If not then the following would work

TC = class(TA)
  procedure DoSomething; override;
end;
..
procedure TC.DoSomething; assembler; nostackframe;
asm
 jmp TA.DoSomething
end;
Andrew Haines
to Andrew Haines
Andrew Haines wrote 19 lines
On 01/15/11 10:30, Andrew Haines wrote: > On 01/14/11 14:38, Torsten Bonde Christiansen wrote: >> Hi List. >> >> Is it possible to jump a couple of levels in the inherited hierarchy >> when calling "inherited" on a method? >> >> > > I *think* I've done this before this way but test it to make sure it works: > > procedure TC.DoSomething: > begin > (Self as TA).DoSomething; > end; > Okay I tested that and it didn't work.

For some reason this problem intrigued me so I played around with it and came up with the attached program that demonstrates a solution that seems not too hackish to me. (Even though it is one). TC.Dosomething calls TA.DoSomething and can also have it's own vars and code.

Regards,

Andrew