假设我们有以下内容:
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中包含的实例,从而隔离所有内容。但我想要一条捷径...
答案 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;