I think this is best explained with some code:
uses
System.SysUtils,
System.Rtti;
type
TFoo = class
procedure X;
end;
TFooHelper = class helper for TFoo
procedure Y;
end;
procedure TFoo.X;
begin
Writeln('TFoo.X');
end;
procedure TFooHelper.Y;
begin
Writeln('TFooHelper.Y');
end;
var
f: TFoo;
ctx: TRttiContext;
t: TRttiType;
m: TRttiMethod;
i: TRttiInterfaceType;
begin
f := TFoo.Create;
f.X;
f.Y;
// Looking at the assembly code for these two calls will show this
// (remember to turn off ASLR if you have a recent Delphi version as that
// disables the possibility to see the method names):
// call TFoo.X
// call TFooHelper.Y
Writeln('Methods of TFoo:');
t := ctx.GetType(TFoo);
for m in t.GetMethods do
Writeln(' ', m.ToString);
// Okay, we don't see that method there, what if...
Writeln;
Writeln('Methods of TFooHelper:');
t := ctx.GetType(TypeInfo(TFooHelper));
for m in t.GetMethods do
Writeln(' ', m.ToString);
// Ah! And it looks like it was inherited from TObject, or? Let's see...
Writeln;
while True do
begin
t := t.BaseType;
if t = nil then Break;
Writeln(t.ToString);
end;
// Oh, there is that TClassHelperBase, and it inherits from TInterfacedObject - I wonder if...
Writeln;
t := ctx.GetType(TypeInfo(TFooHelper));
if t is TRttiInstanceType then
for i in TRttiInstanceType(t).GetDeclaredImplementedInterfaces do
Writeln(i.ToString);
// No, it does not implement any other interfaces.
Readln;
end.
Things get a bit more interesting when you implement virtual methods on the helper because then the compiler puts some interface onto that generated class which you cannot easily get via the GetDeclaredImplementedInterfaces because their TypeInfo is nil. But stepping through the call of a virtual method call will show how it works internally.