实现多个接口的类的清晰度(替代委托):

时间:2011-07-26 20:48:24

标签: 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;        //implementation of IFirst
  function GetOtherStuff: Integer;   //implementation of ISecond;
end;

我从来不喜欢在TInterfacedObject中似乎没有办法区分哪些方法实现哪些接口。我错过了什么吗?有没有人知道代码的方式结构呢?要指定GetStuff是IFirst和GetOtherStuff的实现是ISecond的实现吗? ('发表评论'不是我正在寻找的答案......)

我知道我可以使用'implements'指令为每个接口定义TFirstSecond中的属性,并将实现委托给TFirstSecond中包含的实例,从而隔离所有内容。但我想要一条捷径...

4 个答案:

答案 0 :(得分:15)

我想,如果不使用评论,你唯一能做的就是添加method resolution clauses

IFirst = interface
  function GetStuff: Integer;
end;

ISecond = interface
  function GetOtherStuff: Integer;
end;

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

我认为这并没有给这个组合增添太多,我个人认为这比没有方法解决条款更糟糕。

答案 1 :(得分:11)

在你发布的情况下,我更喜欢评论(接口名称就像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;

你可以说Implements是我们可以做“部分类”的唯一方法,或者至少创建一个实现一堆接口的复合类,并且有一堆子属性(受保护甚至是私有)曾经做过“工具”委托。如果您将其他所有内容移出包含聚合类的单元,那么您可以拥有非常干净的设计。

答案 2 :(得分:2)

虽然你是专门要求不涉及评论的答案,但我可以说使用评论通用解决方案,而不仅仅是Delphi VCL,具体如下:

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

答案 3 :(得分:2)

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;

如果你有很多接口或很多方法,那就是缺点:重复。但是,正如您在示例中所看到的,您不需要为接口中的所有方法指定映射。

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

TMyCombinedObject = class(TInterfacedObject, IMyFirstInterface, IMySecondInterface)
protected
  procedure IMyFirstInterface.DoSomethingInteresting = DoSomethingInterestingFirst;
  procedure DoSomethingInterestingFirst;

  procedure IMySecondInterface.DoSomethingInteresting = DoSomethingInterestingSecond;
  procedure DoSomethingInterestingSecond;

  procedure DoSomethingElse;
end;