【问题标题】:Can an interface be implemented using static methods?可以使用静态方法实现接口吗?
【发布时间】:2014-08-06 13:45:32
【问题描述】:

以下内容无法编译,但有可能吗?

  IDefaultHelp = interface
  ['{6997FC42-7481-4CDA-940A-0351071266C7}']
    function GetTemplate: TXMLDocument;

  end;

  TDefaultHelp = class(TInterfacedObject, INodeHelp)
    class function GetTemplate: TXMLDocument; static;  <<-- error
  end;

我不想实例化实现对象。

有没有办法实现接口而不必Create 一个实际的类?

【问题讨论】:

  • 如果没有实例,谁来跟踪引用计数?
  • 当然,您可能不想要引用计数。因此,如果您正在寻找静态方法的接口,请查看默认比较器接口是如何在泛型单元中实现的。函数指针的记录按 vtable 顺序排列。
  • 是的,这对于非引用接口是可能的;您仍然需要一个实例(没有实例就没有接口),但您可以将实例声明为常量,因此您无需在运行时创建实例。

标签: delphi interface delphi-xe2


【解决方案1】:

我必须承认,我并没有真正看到避免实例化实例的必要性。现在,您不能使用静态类方法来实现接口。如果您愿意,可以通过委托给静态类方法来实现接口。

我不想实例化实现对象。

因此,将您的问题视为实现接口而不需要实例化对象的愿望,您可以使用常量 vtable,以 Generics.Defaults 单元中的比较器接口的方式实现。

例如:

unit Unit1;

interface

uses
  Xml.XMLDoc;

type
  IDefaultHelp = interface
    ['{6997FC42-7481-4CDA-940A-0351071266C7}']
    function GetTemplate: IXMLDocument;
  end;

function GetDefaultHelp: IDefaultHelp;

implementation

function NopAddref(inst: Pointer): Integer; stdcall;
begin
  Result := -1;
end;

function NopRelease(inst: Pointer): Integer; stdcall;
begin
  Result := -1;
end;

function NopQueryInterface(inst: Pointer; const IID: TGUID; out Obj): HResult; 
  stdcall;
begin
  Result := E_NOINTERFACE;
end;

function GetTemplate(inst: Pointer): IXMLDocument;
begin
  Result := TXMLDocument.Create(nil);
end;

const
  DefaultHelp_Vtable: array[0..3] of Pointer =
  (
    @NopQueryInterface,
    @NopAddref,
    @NopRelease,
    @GetTemplate
  );
  DefaultHelp_Instance: Pointer = @DefaultHelp_Vtable;

function GetDefaultHelp: IDefaultHelp;
begin
  Result := IDefaultHelp(@DefaultHelp_Instance);
end;

end.

【讨论】:

  • @user246408,它在 System.Generics 中工作得很好,为什么在这里不能工作?
  • 表示 System.Generics 没有上述错误 ;)
  • @user246408 当我运行它时它可以工作。为什么你认为这是错误的?请务必让我们知道,而不是如此神秘。如果有问题,那么显然我想了解它。
  • 创建 XML 文档?我不相信你。
  • @user246408 我从 Johan 的答案中复制了代码,并没有查看 GetTemplate 的实际作用。我一生中从未创建过 XML 文档。怎么了?好吧,这不是生命时间管理。如果将nil 传递给TXMLDocument 的构造函数,则新对象的生命周期由接口引用管理。试试那个编辑。这就是你的意思。
猜你喜欢
  • 2013-01-12
  • 1970-01-01
  • 1970-01-01
  • 2020-06-23
  • 2012-03-13
  • 1970-01-01
  • 1970-01-01
  • 2011-04-26
  • 2021-07-10
相关资源
最近更新 更多