views:

106

answers:

3

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 reference (IFoo, IFooBar, or TFooBar), without switching between them, and without adding all of IFoo's methods to TFooBar.

A: 

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.

skamradt
The "class vs interface" and missing "read FFoo" were typos. Even correcting them, the example doesn't work. If I have a reference to TFooBar I can't call "FooBar.Foo1"; it's considered undeclared.
Craig Peterson
I believe you need to re-declare the procedures of IFoo in IFooBar if you want to use IFooBar and have them exposed.
skamradt
Skamradt is right. There's no "Interface helper" in Delphi. It would be nice if there was, though. Try adding it in QC.
Mason Wheeler
A: 

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.

Deltics
Apparently my post wasn't clear. I have an 'IFoo' from a third party, which I don't control. I'd like to add additional helper functions to it, like a class helper does. TFooBar and IFooHelper were my proposed syntaxes for how this would occur.
Craig Peterson
A: 

Hi,

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;
LeGEC