Delphi 实现多个接口的类的清晰性(替代委派):

Delphi 实现多个接口的类的清晰性(替代委派):,delphi,interface,implementation,delegation,Delphi,Interface,Implementation,Delegation,假设我们有以下几点: IFirst = Interface(IUnknown) function GetStuff: Integer; end; ISecond = Interface(IUnknown) function GetOtherStuff: Integer; end; TFirstSecond = class(TInterfacedObject, IFirst, ISecond) private function GetStuff: Integer;

假设我们有以下几点:

IFirst = Interface(IUnknown)    
  function GetStuff: Integer;
end;

ISecond = Interface(IUnknown)
  function GetOtherStuff: Integer;
end;

TFirstSecond = class(TInterfacedObject, IFirst, ISecond)    
private 
  function GetStuff: Integer;        //implementation of IFirst
  function GetOtherStuff: Integer;   //implementation of ISecond;
end;
我从来都不喜欢这样一个事实:在TInterfacedObject中,似乎无法区分哪些方法实现了哪些接口。我错过什么了吗?有人知道这样做的方法吗?指定GetStuff是IFirst的实现,GetOtherStuff是ISecond的实现?(“发表评论”不是我想要的答案…)


我知道我可以使用“implements”指令在TFirstSecond中为每个接口定义属性,并将实现委托给TFirstSecond中包含的实例,从而隔离所有内容。但是我想要一个快捷方式…

我想你不使用注释唯一能做的就是添加:


<>我不认为这真的增加了很多,我个人认为这比没有方法解决条款更糟。

虽然你是特别要求一个不涉及评论的答案,但是我可以说,使用评论是更常见的解决方案,而不仅仅是Delphi VCL,如下所要精确:

TFirstSecond = class(TInterfacedObject, IFirst, ISecond)
private
  { IFirst }
  function GetStuff: Integer;
private
  { ISecond }
  function GetOtherStuff: Integer;
end;

在您发布的例子中,我也更喜欢注释(接口名称正如NGLN所说),但我想解释一下为什么implements关键字在其他一些情况下是最好的解决方案,而不是在每个接口只有一个方法的普通情况下,就像在您的普通示例中一样

我知道你说过你知道工具;但是对于那些没有看到它的人,我想记录下它什么时候有用,请耐心听我说。在某些情况下,拥有更多课程的额外工作甚至是值得的

因此,我不会将实现用作快捷方式(正如您所看到的,它更长!),而是仅当每个接口涉及100个要实现的方法,并且最终设计的耦合性更小,内聚性和可读性更好时才使用

所以这是一个公认的愚蠢的例子,但如果IFirst和ISecond中的每一个都有100个方法,那么这可能是一个巨大的飞跃

type
IFirst = interface
  function GetStuff: Integer;
end;

ISecond = interface
  function GetOtherStuff: Integer;
end;

TFirstLogic = class(TInterfacedObject, IFirst)
  function GetStuff: Integer;

end;

TSecondLogic = class(TInterfacedObject, ISecond)
  function GetOtherStuff: Integer;
end;

TFirstSecond = class(TInterfacedObject, IFirst, ISecond)
private
  FFirst:TFirstLogic;
  FSecond:TSecondLogic;
protected


  property First:TFirstLogic read FFirst implements IFirst;
  property Second:TSecondLogic read FSecond implements ISecond;
public
  constructor Create; // don't forget to create and free FFirst/FSecond.
  destructor Destroy; override; // don't forget to create and free FFirst/FSecond.


end;
您可以说实现是我们实现“部分类”的唯一方法,或者至少创建一个实现一组接口的复合类,并拥有一组用于执行“实现”委托的子属性(受保护的,甚至是私有的)。如果您将所有其他内容从包含聚合类的单元中移出,那么您就可以拥有一个非常干净的设计。

D2006(但也可能是较早的版本,D2006只是我目前可用的最早版本),支持将接口方法“映射”到特定的类函数。这样就不需要像处理
implements
关键字那样拥有属性

当两个接口包含相同的方法签名但需要不同的实现时,使用接口映射也应该是消除歧义的一种方法

例如:

IMyFirstInterface = interface(IInterface)
  procedure DoSomethingInteresting;
  procedure DoSomethingElse;
end;

IMySecondInterface = interface(IInterface)
  procedure DoSomethingInteresting;
end;

TMyCombinedObject = class(TInterfacedObject, IMyFirstInterface, IMySecondInterface)
private
  // Interface mappings 
  procedure IMyFirstInterface.DoSomethingInteresting = DoSomethingInterestingFirst;
  procedure IMySecondInterface.DoSomethingInteresting = DoSomethingInterestingSecond;
protected
  procedure DoSomethingInterestingFirst;
  procedure DoSomethingInterestingSecond;
  procedure DoSomethingElse;
end;
如果你有很多接口或方法,缺点是:重复。但是,正如您在示例中看到的,您不需要为接口中的所有方法指定映射

出于文档目的,您可以将映射直接与实际的方法声明放在一起,这样它们就可以保持在一起,并且不太可能不同步(或者更确切地说,映射将丢失新方法,因为您不需要为每个接口方法声明映射):


我忘了那个构造,你提醒了我-虽然我不认为它很糟糕(你的问题是什么?冗余?),但我不认为它真的解决了问题,因为我关心的主要是代码的实现部分-如果我有10个复杂的方法,每个方法对应2个接口,我想让代码自行定义它实现的接口。方法解析并不是为此而设计的——它只是一种避免名称冲突的方法。我想我要么生活在混乱中,要么“振作起来”并使用授权……你们所寻找的并不存在,我相信{实现一件事}为了人类的利益真的应该是一个评论,就是这样。但是,当你必须消除两个方法名称之间的歧义时,方法解析子句真的非常好,否则会发生冲突(当然,在这种情况下,我宁愿100%地只通过授权来消除歧义)。只有人需要帮助,因此,只有注释应该改变。代码是为计算机编写的(你也可以阅读),但如果是你的大脑需要信息,那么注释是理想的。+如果只是界面部分,注释就足够了-正如我在给David的注释中所解释的,我更关心的是实现。在这种情况下,似乎大家的共识是授权是唯一的办法。嗯,我想知道为什么执行会引起任何关注。在接口中,查看类的哪些部分满足接口(契约)是可以理解的,但除此之外,实现的组织方式与接口的方法等问题完全无关,组织更有效的导航成为关键。e、 我把我所有的getter/setter方法放在构造函数/析构函数之后,但放在任何“real”方法之前,并且简单地按字母顺序排列。。。[…续][…续]如果我需要在接口和实现部分之间导航,我总是使用ctrl-up/down键,因此使用其中一个作为“索引”并具体反映另一个的组织是不必要的。如果我在一个方法“Foo”上,并且想要得到一个我知道存在的方法“Bar”,我知道它在“Foo”之前(按字母顺序排列)。同时,在接口中,我可以记录Foo是一个接口合同的一部分,Bar是另一个接口合同的一部分,提供Bar的接口可能在Foo之前。举个例子。同意-看我对沃伦回答的评论。有2个或3个接口,每个接口有15/20个功能。我继承了一大笔遗产
IMyFirstInterface = interface(IInterface)
  procedure DoSomethingInteresting;
  procedure DoSomethingElse;
end;

IMySecondInterface = interface(IInterface)
  procedure DoSomethingInteresting;
end;

TMyCombinedObject = class(TInterfacedObject, IMyFirstInterface, IMySecondInterface)
private
  // Interface mappings 
  procedure IMyFirstInterface.DoSomethingInteresting = DoSomethingInterestingFirst;
  procedure IMySecondInterface.DoSomethingInteresting = DoSomethingInterestingSecond;
protected
  procedure DoSomethingInterestingFirst;
  procedure DoSomethingInterestingSecond;
  procedure DoSomethingElse;
end;
TMyCombinedObject = class(TInterfacedObject, IMyFirstInterface, IMySecondInterface)
protected
  procedure IMyFirstInterface.DoSomethingInteresting = DoSomethingInterestingFirst;
  procedure DoSomethingInterestingFirst;

  procedure IMySecondInterface.DoSomethingInteresting = DoSomethingInterestingSecond;
  procedure DoSomethingInterestingSecond;

  procedure DoSomethingElse;
end;