Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implement a Delphi interface using an 'anonymous' class

Tags:

delphi

I have an interface.

type IProgressObserver = interface(IInterface)
    procedure ReportProgress(Progress:Integer);
    procedure ReportError(Message:string);
end;

I have implemented the interface using a named class, as follows:

type TProgressObserver=class(TInterfacedObject, IProgressObserver)    
    procedure ReportProgress(Progress:Integer);
    procedure ReportError(Message:string);
end;

... implementation of methods go here .....

addProgressObserver(TProgressObserver.Create);

Is it possible to create an instance of this interface without declaring a class? Something like this (imaginary) code, that would do the same thing as above:

 addProgressObserver(IProgressObserver.Create()
 begin
   procedure ReportProgress(Progress:Integer)
   begin
     ShowMessage('Progress Observed!');
   end

   procedure ReportError(Message:string)
   begin
     Log(Message);
   end
 end;);

Delphi has anonymous procedures, but does it have anonymous classes??

I found this similar question, but it's in Java.

I am using Delphi 2010

like image 337
awmross Avatar asked Jul 22 '11 06:07

awmross


2 Answers

You can get pretty anonymous, implementing the interface using anonymous methods. But you don't get actual compiler support for this, you'll have to declare all the anonymous method types yourself, then implement the actual "anonymous" class. Given your IProgressObserver interface, the implementation would look something like this:

type
  // This is the interface we'll be dealing with.
  IProgressObserver = interface(IInterface)
    procedure ReportProgress(Progress:Integer);
    procedure ReportError(Message:string);
  end;

  // This will help us anonymously create implementations of the IProgressObserver
  // interface.
  TAnonymousObserverImp = class(TInterfacedObject, IProgressObserver)
  type
    // Declare reference types for all the methods the interface needs.
    TReportProgressProc = reference to procedure(Progress:Integer);
    TReportErrorProc = reference to procedure(Message:string);
  strict private
    FReportProgressProc: TReportProgressProc;
    FReportErrorProc: TReportErrorProc;

    // Actual implementation of interface methods.
    procedure ReportProgress(Progress:Integer);
    procedure ReportError(Message:string);
    // private constructor, so we'll forced to use the public "Construct" function
    constructor Create(aReportProgressProc: TReportProgressProc; aReportErrorProc: TReportErrorProc);
  public
    // This takes the required anonymous methods as parameters and constructs an anonymous implementation
    // of the IProgressObserver interface.
    class function Construct(aReportProgressProc: TReportProgressProc; aReportErrorProc: TReportErrorProc): IProgressObserver;
  end;

{ TAnonymousObserverImp }

class function TAnonymousObserverImp.Construct(
  aReportProgressProc: TReportProgressProc;
  aReportErrorProc: TReportErrorProc): IProgressObserver;
begin
  // Call the private constructor
  Result := TAnonymousObserverImp.Create(aReportProgressProc, aReportErrorProc);
end;

constructor TAnonymousObserverImp.Create(
  aReportProgressProc: TReportProgressProc; aReportErrorProc: TReportErrorProc);
begin
  inherited Create;
  // We simply save the references for later use
  FReportProgressProc := aReportProgressProc;
  FReportErrorProc := aReportErrorProc;
end;

procedure TAnonymousObserverImp.ReportError(Message: string);
begin
  // Delegate to anonymous method
  FReportErrorProc(Message);
end;

procedure TAnonymousObserverImp.ReportProgress(Progress: Integer);
begin
  // Delegate to anonymous method
  FReportProgressProc(Progress);
end;

Once all that code is in place you'll be able to write code like this:

var i: IProgressObserver;
begin
  i := TAnonymousObserverImp.Construct(
    procedure (Progress:Integer)
    begin
      // Do something with Progress
    end
    ,
    procedure (Message:string)
    begin
      // Do something with Message
    end
  )
end;

Looks pretty anonymous to me! Given the implementation of anonymous methods in Delphi it's also fairly fast and effective.

like image 148
Cosmin Prund Avatar answered Nov 17 '22 08:11

Cosmin Prund


Short answer I'm afraid: sorry, no, Delphi doesn't have anonymous classes.

like image 6
Marjan Venema Avatar answered Nov 17 '22 09:11

Marjan Venema