开发者

Interface helpers or delegating interface parent

If I have an existing IInterface descendant implemented by a third party, and I want to add helper routines, does Delphi provide any easy way to do so without redirecting every interface method manually? That is, given an interface like so:

IFoo = interface
  procedure Foo1;
  procedure Foo2;
  ...
  procedure FooN;
end;

Is anything similar to the following supported?

IFooHelper = interface helper for IFoo
  procedure Bar;
end;

or

IFooBar = interface(IFoo)
  procedure Bar;
end;

TFooBar = class(TInterfacedObject, IFoo, IFooBar)
private
  FFoo: IFoo;
public
  procedure Bar;
  property Foo: IFoo read FFoo implements IFoo;
end;

I'm specifically wondering about ways to that allow me to always call Foo1, Foo2, and Bar with a single variable re开发者_JAVA百科ference (IFoo, IFooBar, or TFooBar), without switching between them, and without adding all of IFoo's methods to TFooBar.


Change your class to read:

TFooBar = Class(TInterfacedObject, IFoo, IFooBar)
private
  FFoo: IFoo;
public
  procedure Bar;
  property Foo: IFoo read FFoo implements IFoo ;
end;

You will also need a constructor or some method to create the instance of IFoo and place it in FFoo.


You cannot access the methods of IFoo through a reference to TFooBar because TFooBar doesn't implement IFoo - it delegates IFoo. But you shouldn't be using a TFooBar reference to access an interfaced object anyway, that's the whole point of using interfaces in the first place!

NOTE: To deliberately prevent this I adopt a convention of implementing interface methods on my classes as "protected", specifically to deny access to those implementation details except as surfaced via the interface itself.

Where-ever you are currently obtaining a reference to TFooBar, change this to instead obtain the IFooBar interface implemented by TFooBar and you will be sorted.


I'm not sure I understood all of your concerns, but here's my suggestion anyway :

IFooBar = interface(IFoo)
  procedure Bar;
end;

TFooDelegate = class(TInterfacedObject, IFoo )
private
  FFoo: IFoo;
public
  property Foo: IFoo read FFoo implements IFoo;
end;

TFooBar = class( TFooDelegate, IFooBar )
  procedure Bar;
end;


see https://docwiki.embarcadero.com/RADStudio/Sydney/en/Implementing_Interfaces:_Delphi_and_C%2B%2B on how to use TAggregatedObject together with "implements" syntax at a property

quoting from there:

unit Unit1;
 
 interface
 
 type
 
  // Interface that exposes an 'Add' method
  IAdder = interface
  ['{D0C74612-9E4D-459A-9304-FACE27E3577D}']
    function Add(I, J: Integer): Integer;
  end;
 
  // Aggregatee that implements IAdder
  TAdder = class(TAggregatedObject, IAdder)
    function Add(I, J: Integer): Integer;
  end;
 
  // Aggregator - implements IAdder via TAdder
  TPasClass = class(TInterfacedObject, IAdder)
    FAdder: TAdder;
    function GetAdder: TAdder;
  public
    destructor Destroy; override;
    property Adder: TAdder read GetAdder write FAdder implements IAdder;
  end;
 
 function TestAdd(I, J: Integer): Integer; 
 
 implementation
 
 { TAdder }
 function TAdder.Add(I, J: Integer): Integer;
 begin
   Result := I+J;
 end;
 
 { TPasClass }
 destructor TPasClass.Destroy;
 begin
   FAdder.Free;
   inherited;
 end;
 
 function TPasClass.GetAdder: TAdder;
 begin
   if FAdder = nil then
     FAdder := TAdder.Create(Self as IInterface);
   Result := FAdder;
 end;
 
 // Adds using TClass' IAdder
 function TestAdd(I, J: Integer): Integer; 
 var
   punk: IInterface;
 begin
   punk := TPasClass.Create as IInterface;
   Result := (punk as IAdder).Add(I, J);
 end;
 
 end.

however it would be nice if one could do:

TSomeClassIFoo123Helper = class helper(IFoo1, IFoo2, IFoo3) for TSomeClass
  procedure Bar1;
  procedure Bar2;
  procedure Bar3;
end;

injecting IFoo1, IFoo2, IFoo3 interface implementations into TSomeClass. The helpers support inheritance, but can only specify another helper class at the list, not one ore more interfaces there

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜