Delphi 我不知道';I don’我不知道我是否需要或者如何实现接口的这三种基本方法
我想实现一个接口,但我不能从Delphi 我不知道';I don’我不知道我是否需要或者如何实现接口的这三种基本方法,delphi,interface,delphi-10.3-rio,Delphi,Interface,Delphi 10.3 Rio,我想实现一个接口,但我不能从TInterfacedObject声明它,在这种情况下,文档说明我必须实现QueryInterface,\u AddRef,\u Release。但我不确定这是否是强制性的。到目前为止,我还没有真正使用过接口。。。关于COM对象的一些东西,但我甚至不知道这意味着什么。我从来没有故意使用COM对象,也许只有当它们包含在我从互联网上获取的一些代码中时。我尝试了一个例子(见下文),但它没有实现这3种方法。所以 我怎么知道我是否必须执行它们 如果我必须实施它们,我该怎么做?我
TInterfacedObject
声明它,在这种情况下,文档说明我必须实现QueryInterface
,\u AddRef
,\u Release
。但我不确定这是否是强制性的。到目前为止,我还没有真正使用过接口。。。关于COM对象的一些东西,但我甚至不知道这意味着什么。我从来没有故意使用COM对象,也许只有当它们包含在我从互联网上获取的一些代码中时。我尝试了一个例子(见下文),但它没有实现这3种方法。所以
TInterfacedObject
复制实现吗?(事实上,它有3个以上…那些额外的也必须复制?)unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;
type
IShellInterface = interface
['{55967E6B-5309-4AD0-B6E6-739D97A50626}']
procedure SetPath(const APath: String);
function GetPath: String;
end;
TDriveBar = class(TCustomPanel, IShellInterface)
private
FDriveLink: IShellInterface;
FPath: String;
public
procedure SetPath(const APath: String);
function GetPath: String;
property DriveLink: IShellInterface read FDriveLink write FDriveLink;
end;
TForm1 = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
DriveBar1, DriveBar2: TDriveBar;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TDriveBar.SetPath(const APath: String);
begin
FPath:= APath;
Caption:= APath;
end;
function TDriveBar.GetPath: String;
begin
Result:= FPath;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
ReportMemoryLeaksOnShutdown:= True;
DriveBar1:= TDriveBar.Create(Form1);
DriveBar1.Parent:= Form1;
DriveBar1.SetBounds(20, 20, 250, 40);
DriveBar1.SetPath('Drive Bar 1');
DriveBar2:= TDriveBar.Create(Form1);
DriveBar2.Parent:= Form1;
DriveBar2.SetBounds(20, 80, 250, 40);
DriveBar2.SetPath('Drive Bar 2');
DriveBar1.DriveLink:= DriveBar2;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
DriveBar1.DriveLink.SetPath('D:\Software\Test');
Caption:= DriveBar2.GetPath;
end;
end.
任何支持接口的类都必须实现所有三种方法:
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
若从中继承的基类实现了这些方法,那个么就不需要实现它们。如果基类没有它们,代码将无法编译
不同的类对这些方法和主要方法有不同的实现,最重要的区别在于是否启用了自动引用计数
如果启用了引用计数,则应始终在接口引用中存储此类类的实例(变量类型必须为interface),如果禁用,则可以使用对象引用
如果启用,ARC将自动管理该实例的内存,如果禁用,则需要手动释放该实例
例如,启用引用计数的类是TInterfacedObject
,在大多数情况下禁用引用计数的类是TComponent
(用作COM对象容器的情况除外)
基本上,在最简单的场景中,如果\u AddRef
和\u Release
只返回-1
,则将禁用引用计数。如果需要实现引用计数,那么复制代码或从中继承代码的最佳模板是TInterfacedObject
QueryInterface
的目的是为Support
函数添加功能,并为受支持的guid查询接口。如果不确定要放在那里的内容,则无论是否启用了ARC,都可以始终使用TInterfacedObject
实现
根据传递给构造函数的相同值,也可以使类禁用或启用ARC。此类类的示例为TXMLDocument
,其中如果nil
作为Owner
传递,则启用ARC,否则禁用ARC
在您的示例中,
TCustomPanel
继承自已经实现了这些方法的TComponent
,因此您不必做任何事情。不清楚您在问什么。您的示例继承自TIntefacedObject,因此这些方法已经实现。简而言之,是的,您始终需要在支持接口的类中实现这些方法。你们应该如何实现它们取决于各种事情,你们首先要回答的是你们是否想让这个类启用自动引用计数。啊,对不起!我纠正了。应该有TCustomPanel
…TCustomPanel是TComponent的后代,TComponent实现了这些方法,您不必做任何事情。另外,若你们从并没有那个些方法的类继承,你们将无法编译你们的代码。哇,我很高兴听到这个!多幸运啊!:)