【问题标题】:Implement a Delphi interface using an 'anonymous' class使用“匿名”类实现 Delphi 接口
【发布时间】:2011-07-22 06:24:16
【问题描述】:

我有一个界面。

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

我已经使用命名类实现了接口,如下:

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

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

addProgressObserver(TProgressObserver.Create);

是否可以在不声明类的情况下创建此接口的实例?像这样的(虚构的)代码,它会做和上面一样的事情:

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

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

Delphi 有匿名过程,但它有匿名类吗??

我找到了this similar question,但它是用 Java 编写的。

我使用的是 Delphi 2010

【问题讨论】:

    标签: delphi


    【解决方案1】:

    可以变得非常匿名,使用匿名方法实现接口。但是你没有得到实际的编译器支持,你必须自己声明所有匿名方法类型,然后实现实际的“匿名”类。给定你的IProgressObserver 接口,实现看起来像这样:

    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;
    

    一旦所有代码都到位,您就可以编写如下代码:

    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;
    

    对我来说看起来很匿名!鉴于 Delphi 中匿名方法的实现,它也相当快速和有效。

    【讨论】:

    • 哇!很好的答案(假设它有效……我还没有测试过)。当然,如果您只创建一次实例(我就是这样),那么代码会更多。在我的例子中,创建一个命名类要容易得多,但是如果你正在编写一个被数百万程序员使用的 3rd 方库,这将是要走的路。我想知道是否所有这些样板都可以自动生成?
    • @awmross,当然可以,我在发布之前测试了我的代码!自动生成样板文件应该不是什么大问题,但如果编译器这样做会更好。
    • 虽然这当然很聪明,但我正在努力看看什么时候这会特别有用。
    • @David,我正在使用类似的东西来实现枚举器,它非常方便。 VCL 本身在TDelegatedComparer<T> 中也是如此,我相信还有其他示例。
    • @David,有一些痛苦,尤其是对于像 OP 示例这样的小型接口:您需要声明一个类和一些方法+实现,而这些都不能是实际需要的过程的本地接口实例。使用这样的匿名实现将实现保持在逻辑上需要的地方,并且不会污染命名空间。我将再次给出TDelegatedComparer<T> 的示例:我讨厌预泛型TList.Sort() 调用所需的全局函数!
    【解决方案2】:

    恐怕简短的回答:对不起,不,Delphi 没有匿名类。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 2019-12-20
    相关资源
    最近更新 更多