One of these rare moments when the compiler positively impresses me

One of these rare moments when the compiler positively impresses me

See this short and incomplete nonsense code:

type
IFoo = interface
procedure Bar;
end;

TBoo = class
end;

TBooHelper = class helper for TBoo
procedure Bar;
end;

TBar = class(TInterfacedObject, IFoo)
private
fBoo: TBoo;
property Boo: TBoo read fBoo implements IFoo;
end;

The thing that impressed me here was the fact that the interface delegation clause supports class helpers - very nice!

In production code this enables me to use interface delegation to some object without the need to create some wrapper/adapter object.

Comments

  1. How would you use the helper? InstanceOfTBar.Boo.Bar? What's the benefit?

    ReplyDelete
  2. Until someone figures out that this is not a feature but just unfortunate side effect and should be removed ;-)

    ReplyDelete
  3. Christopher Wosinski I don't use the helper. The helper makes the code compile because now TBar satisfies the IFoo interface because the Bar method is provided by TBoo. (see http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Implementing_Interfaces#Delegating_to_a_Class-Type_Property)

    Dalija Prasnikar Don't they dare! ;)

    ReplyDelete
  4. An interesting variance: place the Bar method into TBar and remove the helper completely - it also compiles even if TBoo still lacks implementing IFoo.Bar.

    ReplyDelete
  5. Thanks, got it. Since I don't like interface delegation at all due to the need to inherit from TAggregatedObject I wouldn't trust interface implementation by class helpers either. But why don't live dangerous? At least you use source control and can roll back whenever you want ;-)

    ReplyDelete
  6. Uwe Raabe Which requires me to write that adapter code myself and probably violate SRP since I put code into TBar that belongs to TBooExtension or TBooAdapter. And it would require to write the same code also for all the other classes that possibly implement but delegate that IFoo interface.
    How would that be clean code?

    Christopher Wosinski "need to inherit from TAggregatedObject"
    Which is wrong.

    ReplyDelete
  7. Stefan Glienke It wasn't meant as an alternative way to achieve your target - just another unexpected thing the compiler does.

    ReplyDelete
  8. Uwe Raabe Ok, well not unexpected to me because I knew that delegating to an object property just adds all the methods it can unlike delegating to an interface property (which is the case where you might want to use a TAggregatedObject implementation because it also delegates the IInterface methods) because the documentation explains that - it does not explicitly mention helpers though.

    ReplyDelete
  9. Stefan Glienke If you don't inherit from TAggeegatedObject you get the strangest effects when using interface delegation due to the separated reference counting in the delegated object. Do you know an alternative solution to TAggregatedObject?

    ReplyDelete
  10. Christopher Wosinski Interface delegation to an object property does not separate reference counting. The instance behind the interface is still the container object. The compiler just generated proper stub methods to redirect the method call to the methods it found in the delegatee.

    As I wrote in my previous comment this only happens when delegating to an interface property because then its an all or nothing thing in terms of what methods are being delegated.

    ReplyDelete
  11. I use similar "trick" with helper for FireDAC connection to get IConnection interface with additionals method that are not available in TFDConnection

    ReplyDelete
  12. Stefan Glienke Thanks for the info! Just checked it and it 's working well. Didn't know I can do proper interface delegation without TAggregatedObject. That was always a show stopper for me.

    ReplyDelete

Post a Comment