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
精彩评论