在Delphi中实现接口时,实现方法不在公共部分有关系吗?

RED*_*KEY 3 delphi interface

鉴于以下界面:

ITest = interface ['guidhere']
  procedure TestMethod;
end;
Run Code Online (Sandbox Code Playgroud)

是否有任何理由在实现类中TestMethod()声明为 as public?我已经把它放在privateprotected部分,它似乎没有什么区别。我只是想知道是否有任何指导方针,从设计角度(或任何角度),使该public部分成为实现该方法的正确部分。

Joh*_*ica 5

实现方法不在公共部分有关系吗?

就编译器而言。没有什么不同的。

话虽如此。私有方法仍然是私有的,即使您可以通过接口访问它们。

unit unit1;
....
IItest = interface
  ['{A3D5FEB6-8E29-4EA8-8DC9-7988294EFA65}']
  procedure Test;
end;

TTest = class(TInterfacedObject, IItest)
private
  procedure Test;
end;

unit unit2;
....
var
  TestT: TTest;
  TestI: ITest;
begin
  TestT:= TTest.Create;
  TestI:= TTest.Create;
  TestT.Test;  //will not compile.
  TestI.Test;  //works.
Run Code Online (Sandbox Code Playgroud)

这样做的原因是接口在其 VMT 中只有一个指向方法的指针列表。方法的定义在接口定义中给出。
编译器只检查签名是否匹配。
它不检查方法的可见性。

根据艾伦的评论,这是一个深思熟虑的设计:

将方法设为私有或受保护将确保您只能通过接口访问它们。这是一种为对象的预期用途强制执行使用合同的方法。

请注意,这不是错误,甚至不是坏事。
属性也可以“访问”私有方法:

property Items[index: integer] read GetItem write SetItem;  
Run Code Online (Sandbox Code Playgroud)

这里的 GetItem 和 SetItem 通常是私有的。
这会强制您使用该属性访问 Items。
使用属性时,实现方法通常是受保护的(或更糟的是:-)。相同的逻辑适用于属性和接口。

接口更是如此,因为如果您混合接口访问和常规访问,您将遇到引用计数问题。

干净的代码
请注意,您可以在类标题中拥有任意数量的可见性部分。
通过这种方式,您可以将所有接口方法放在一个部分,而将所有非接口方法放在另一个部分。

TTest = class(TInterfacedObject, I1, I2)
//I1 methods
private
  ... private I1 methods here...
protected
  .. more I1 methods
//I2 methods
private
  .. some I2 methods
protected
  ..more I2 methods     
//TTest methods
private
  //data members
public
  constructor Create;
  destructor Destroy; override;
end;
Run Code Online (Sandbox Code Playgroud)

这样就可以清楚地知道什么是什么。