Advertisement
Guest User

Untitled

a guest
Apr 4th, 2014
29
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 2.21 KB | None | 0 0
  1. program Project1;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. {$R *.res}
  6.  
  7. uses
  8.   System.SysUtils;
  9.  
  10. type
  11.   IBase = interface
  12.     procedure Foo;
  13.   end;
  14.  
  15.   ISub = interface (IBase)
  16.     procedure Bar;
  17.   end;
  18.  
  19.   ISpecialBase = interface (IBase)
  20.   end;
  21.  
  22.   ISpecialSub = interface (ISub)
  23.   end;
  24.  
  25.   TMyClass = class(TInterfacedObject, ISpecialBase, ISpecialSub)
  26.  
  27.     procedure SpecialFoo1;
  28.     procedure SpecialFoo2;
  29.     procedure SpecialBar;
  30.  
  31.     procedure ISpecialBase.Foo = SpecialFoo1;
  32.  
  33.     procedure ISpecialSub.Foo = SpecialFoo2;
  34.     procedure ISpecialSub.Bar = SpecialBar;
  35.  
  36.     function GetTheRightOne(const Param: boolean) : IBase;
  37.   end;
  38.  
  39.  
  40. { TMyClass }
  41.  
  42. function TMyClass.GetTheRightOne(const Param: boolean): IBase;
  43. begin
  44.   if Param then
  45.     Result := ISpecialBase(Self)
  46.   else
  47.     Result := ISpecialSub(Self);
  48. end;
  49.  
  50. procedure TMyClass.SpecialBar;
  51. begin
  52.   WriteLn('SubBar');
  53. end;
  54.  
  55. procedure TMyClass.SpecialFoo1;
  56. begin
  57.   WriteLn('BaseFoo');
  58. end;
  59.  
  60. procedure TMyClass.SpecialFoo2;
  61. begin
  62.   WriteLn('SubFoo');
  63. end;
  64.  
  65. function GetSub(const Intf: IInterface): ISub;
  66. type
  67.   PPVtable = ^PVtable;
  68.   PVtable = ^TVtable;
  69.   TVtable = array[0..MaxInt div SizeOf(Pointer) - 1] of Pointer;
  70. var
  71.   intfVTable: PPVtable;
  72.   caddr: NativeUInt;
  73. begin
  74.   result := nil;
  75.   intfVTable := PPVTable(Intf);
  76.   // 3 is offset to user methods
  77.   // +0 = first user method, +1 = second user method etc
  78.   // get the "address" of the first method in ISub
  79.   caddr := NativeUInt(intfVTable^[3+1]);
  80.   // compiler stores number of interface entries the
  81.   // implementing object implements right after the interface vtable
  82.   // so if we get a low number here, it means Intf is the IBase interface
  83.   // and not the ISub
  84.   if caddr > $100 then
  85.     result := ISub(Intf);
  86. end;
  87.  
  88. procedure CallIt(const b: IBase);
  89. var
  90.   s: ISub;
  91. begin
  92.   b.Foo;
  93.  
  94.   s := GetSub(b);
  95.   if Assigned(s) then
  96.     s.Bar;
  97. end;
  98.  
  99. var
  100.   c: TMyClass;
  101.   b: IBase;
  102. begin
  103.   try
  104.     c := TMyClass.Create;
  105.  
  106.     b := c.GetTheRightOne(True);
  107.     CallIt(b);
  108.  
  109.     WriteLn('---');
  110.  
  111.     b := c.GetTheRightOne(False);
  112.     CallIt(b);
  113.  
  114.     WriteLn('...');
  115.  
  116.   except
  117.     on E: Exception do
  118.       Writeln(E.ClassName, ': ', E.Message);
  119.   end;
  120.   ReadLn;
  121. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement