尝试理解Delphi接口

尝试理解Delphi接口,delphi,interface,Delphi,Interface,我正在读Nick Hodges的书“Delphi中的编码”,我试图理解接口的用法。 在一个单元中,我放置了一个简单的接口: unit INameInterface; interface type IName = interface ['{CE5E1B61-6F44-472B-AE9E-54FF1CAE0D70}'] function FirstName: string; function LastName: string; end; implementation

我正在读Nick Hodges的书“Delphi中的编码”,我试图理解接口的用法。 在一个单元中,我放置了一个简单的接口:

unit INameInterface;

interface

type
  IName = interface
  ['{CE5E1B61-6F44-472B-AE9E-54FF1CAE0D70}']
    function FirstName: string;
    function LastName: string;
  end;

implementation

end.
在另一个单元中,我介绍了这个接口的实现,与书中的示例一致:

unit INameImplementation;

interface

uses
  INameInterface;

type
  TPerson = class(TInterfacedObject, IName)
    protected
      function FirstName: string;
      function LastName: string;
  end;

implementation

{ TPerson }

function TPerson.FirstName: string;
begin
  Result := 'Fred';
end;

function TPerson.LastName: string;
begin
  Result := 'Flinstone';
end;

end.
此时,我创建了一个简单的VCL表单应用程序,以便使用我创建的对象。表格代码如下:

unit main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  Vcl.StdCtrls, INameImplementation;

type
  TfrmMain = class(TForm)
    lblFirtName: TLabel;
    lblLastName: TLabel;
    txtFirstName: TStaticText;
    txtLastName: TStaticText;
    btnGetName: TButton;
    procedure btnGetNameClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    Person: TPerson;
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  txtFirstName.Caption := '';
  txtLastName.Caption := '';
end;

procedure TfrmMain.btnGetNameClick(Sender: TObject);
begin
  txtFirstName.Caption := ...
end;

end.
我的问题是:如何使用该界面?这两个函数声明为受保护,因此如何从窗体访问它们?我必须将它们定义为public,还是应该使用INameInterface接口单元? 我对接口非常困惑


性爱本质上有三件事需要你去了解,超出你已经表现出的理解

1。如何调用接口的方法

如果有对接口的引用,则可以像调用类引用一样调用方法:

var
  Name: IName;
....
Writeln(Name.FirstName);
Writeln(Name.LastName);
2。如何获取接口参考

通常,可以通过实例化一个实现要使用的接口的类来完成此操作:

var
  Name: IName;
....
Name := TPerson.Create;
// now you can use Name as before
还有其他方法可以获得接口引用,但是现在让我们把它们放在一边

3。如何传递接口

您可能不希望每次需要使用接口时都创建新对象。因此,您可以让其他各方向您传递要使用的接口。例如,实例接口可以作为方法参数传递:

procedure Foo(Name: IName);
begin
  // use Name as before
end;
您可以通过函数调用和属性等获取接口引用


这两个函数被声明为受保护的,因此如何从表单中访问它们

嗯,它们在实现对象中声明为
受保护的
。但您不会通过实现对象访问它们。您将通过接口访问它们。这意味着实现对象中的可见性与接口的角度无关

表单单元引用了MeiImplementation中的
,这是创建实现接口的对象所必需的。您还需要在接口中使用
INameInterface
,以便代码可以看到接口本身


这个示例还不是很强大,因为您仍然可以看到实现对象的类型。但是想象一下,如果这对你来说是隐藏的,你所能看到的只是一个函数,它返回了一个
IName
。当您达到这一点时,接口才能发挥其潜力

比大卫更重要的是。还有一个问题:所以我必须在主单元的uses子句中包含INameInterface和INameImplementation。这是这类对象的正常用法吗?关于接口还有很多要说的,但我试着坚持基本原则。我相信nick的书中还说了很多。@Eros:所有接口消费者都应该只引用接口单元。依赖注入很自然地适合这种类型的编码。我认为我们的OP还没有准备好进行那种程度的心理训练。一个关于如何使用接口的好例子。。。假设您有一个DLL,其中有一个对象,您也希望在调用过程中使用该对象。不能跨DLL边界传递对象,但可以传递接口(只要接口的成员也是安全的,例如WideString而不是String)。然后,实例化DLL中的对象,并将该对象的接口引用从DLL传递回调用应用程序-然后调用应用程序可以与该接口进行交互,就像直接调用对象一样。@Jerry这更像是二进制互操作的实现问题。我认为接口是一个更深层次的概念。