Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 我不知道';I don’我不知道我是否需要或者如何实现接口的这三种基本方法_Delphi_Interface_Delphi 10.3 Rio - Fatal编程技术网

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实现了这些方法,您不必做任何事情。另外,若你们从并没有那个些方法的类继承,你们将无法编译你们的代码。哇,我很高兴听到这个!多幸运啊!:)