Delphi Interface Helpers / Workarounds

I understand that Delphi does not support front-end helpers, but after reading a few topics and sources of Spring4D, etc., I wonder if there is a way to achieve the following? The comments on the source code pretty much summarize what I'm trying to do, so here it is:

program IHelper; {$APPTYPE CONSOLE} {$R *.res} uses Spring, System.SysUtils; type IMyThing = interface ['{01E799A5-9141-4C5E-AA85-B7C9792024D9}'] procedure BasicThing; end; TMyThing = class(TInterfacedObject, IMyThing) strict private procedure BasicThing; end; IMyThingHelper = record private FOutage: IMyThing; public class operator Implicit(const Value: IMyThing): IMyThingHelper; procedure HelpfulThing; end; TMyThingHelper = class helper for TMyThing public class procedure ObjectThing; end; { TOutage } procedure TMyThing.BasicThing; begin Writeln('Basic Thing'); end; { IOutageHelper } procedure IMyThingHelper.HelpfulThing; begin Writeln('Helpful thing'); end; class operator IMyThingHelper.Implicit(const Value: IMyThing): IMyThingHelper; begin Result.FOutage := Value; end; { TMyThingHelper } class procedure TMyThingHelper.ObjectThing; begin Writeln('Object thing'); end; var LThing: IMyThing; begin try LThing := TMyThing.Create; LThing.BasicThing; //LThing.HelpfulThing; // <--- **** prefer this syntax but obviously does not compile IMyThingHelper(LThing).HelpfulThing; // <--- this works ok but prefer not to have to cast it here //LThing.ObjectThing; // <--- obviously does not compile (LThing as TMyThing).ObjectThing; // <--- class helpers work ok but no good for interfaces Readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. 

Any ideas or suggestions on how this code could be made to work where shown with ****? I understand that the answer may be a frank no, but it seems that there are some pretty smart workarounds, and maybe someone is much smarter than I know how to do this? (Delphi XE5)

Thanks.

+8
interface delphi delphi-xe5 spring4d
source share
3 answers

Why not just use a different interface?

 program IHelper; {$APPTYPE CONSOLE} {$R *.res} uses Spring, System.SysUtils; type IMyThing = interface ['{01E799A5-9141-4C5E-AA85-B7C9792024D9}'] procedure BasicThing; end; IMyThingHelper = interface ['{...}'] procedure HelpfulThing; end; TMyThing = class(TInterfacedObject, IMyThing, IMyThingHelper) strict private procedure BasicThing; procedure HelpfulThing; end; { TOutage } procedure TMyThing.BasicThing; begin Writeln('Basic Thing'); end; { IOutageHelper } procedure TMyThing.HelpfulThing; begin Writeln('Helpful thing'); end; var LThing: IMyThing; LHelper: IMyThingHelper; begin try LThing := TMyThing.Create; LThing.BasicThing; if Supports(LThing, IMyThingHelper, LHelper) then LHelper.HelpfulThing; Readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. 
+3
source share

There are two ways to achieve this:

  • One of them will have an IMyThingHelper variable and assign you its own interface, and then call the "extension method" in the record variable.

  • Another would be to use absolute :


 var LThing: IMyThing; LHelper: IMyThingHelper absolute LThing; begin LThing := TMyThing.Create; LHelper.HelpfulThing; 

I wrote about this problem a while ago. Unfortunately, in my case, the "helper record" Enumerable<T> had so many common methods that the compiler slowed down a lot.

+2
source share

Another way to achieve this is to convince Idera to implement this feature. You can enhance this feature request to help with this https://quality.embarcadero.com/browse/RSP-16763

+1
source share

All Articles