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

kiz8lqtg  于 2022-12-29  发布在  其他
关注(0)|答案(4)|浏览(179)

假设我们有以下内容:

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中似乎没有办法区分哪些方法实现哪些接口的事实。我错过了什么吗?有人知道如何构造代码来做到这一点吗?指定GetStuffIFirst的实现,GetOtherStuffISecond的实现?(“发表评论”不是我想要的答案...)
我知道我可以使用'implements'指令在TFirstSecond中为每个接口定义属性,并将实现委托给包含在TFirstSecond中的示例,从而隔离所有内容。

1aaf6o9v

1aaf6o9v1#

我想,不使用注解唯一能做的事情就是添加方法解析子句:

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;

我不认为这真的增加了很多,我个人认为这比没有方法解析子句更糟糕。

mzillmmw

mzillmmw2#

在您发布的案例中,我也更喜欢注解(正如NGLN所说的接口名称),但我想解释一下为什么implements关键字在其他一些案例中可能是最佳解决方案,而不是像您的平凡示例中那样每个接口只有一个方法的平凡案例。
我知道你说过你了解“工具”但是对于那些还没有看过的人,我想记录下它什么时候有用,请耐心听我说,在某些情况下,上更多的课甚至是值得的。
所以我不会把implements作为一种快捷方式(正如你所看到的那样,它更长!),而只是在每个接口涉及100个要实现的方法,并且最终的设计只有更少的耦合,更好的内聚性和可读性的情况下才使用implements。
所以这是一个公认的愚蠢的例子,但是如果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;

你可以说实现是我们可以做“部分类”的唯一方法,或者至少创建一个复合类来实现一堆接口,并拥有一堆用于“实现”委托的子属性(它们是受保护的,甚至可能是私有的)。如果你把其他所有东西都从包含聚合类的单元中移出来,你就可以拥有一个真正干净的设计。

vecaoik1

vecaoik13#

虽然您特别要求一个不涉及注解的答案,但我可以说使用注解 * 是 * Delphi VCL常用的解决方案,具体如下:

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

1l5u6lss4#

D2006(可能还有更早的版本,D2006只是我目前可用的最早版本)支持接口方法到特定类函数的"Map",这就不需要像使用implements关键字那样使用属性。
当两个接口包含相同的方法签名但需要不同的实现时,使用接口Map也应该是一种消除歧义的方法。
示例:

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;

如果有很多接口或方法,则缺点是:然而,正如你在例子中所看到的,你不需要为接口中的所有方法指定Map。
出于文档的目的,你可以直接把Map和实际的方法声明放在一起,这样它们就可以保持在一起,不太可能失去同步(或者说,Map会错过新的方法,因为你不需要为每个接口方法声明一个Map):

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

  procedure IMySecondInterface.DoSomethingInteresting = DoSomethingInterestingSecond;
  procedure DoSomethingInterestingSecond;

  procedure DoSomethingElse;
end;

相关问题