我已经使用 Delphi 类有一段时间了,但是从来没有真正进入使用接口的领域。我已经读了一些关于它们的东西,但是想学习更多。我想听听你在 Delphi 中使用接口时遇到的关于编码、性能、可维护性、代码清晰度、层分离以及一般来说你能想到的任何方面的优点和缺点。
qmb5sa221#
我现在能想到的就是:优点:
缺点:
luaexgnf2#
除了这些答案之外,还有一些优势:1.使用接口来表示行为,并且行为的每个实现都将实现接口。
sd2nnvve3#
我要说的是,没有引用计数的接口在我对 Delphi 的愿望清单上非常高!!!接口的真实的用途是接口的声明,而不是引用计数的能力!
avkwfej44#
界面有一些微妙的缺点,我不知道人们在使用它们时是否考虑到了:1.调试变得更加困难。我在调试器中看到过很多奇怪的困难,在步入接口方法调用时。
oymdgrw75#
当我希望具有不同祖先的对象提供一个公共服务时,我通常会使用接口,根据我自己的经验,我能想到的最好的例子是一个名为IClipboard的接口:
IClipboard
IClipboard = interface function CopyAvailable: Boolean; function PasteAvailable(const Value: string): Boolean; function CutAvailable: Boolean; function SelectAllAvailable: Boolean; procedure Copy; procedure Paste(const Value: string); procedure Cut; procedure SelectAll; end;
我有一堆从标准VCL控件派生而来的自定义控件,它们都实现了这个接口,当剪贴板操作到达我的一个窗体时,它会查看活动控件是否支持这个接口,如果支持,则调度相应的方法。对于一个非常简单的接口,你可以用of object事件处理器来完成,但是一旦它变得足够复杂,接口就可以很好地工作。事实上,我认为这是一个非常好的类比。使用一个单一of object事件不适合功能的接口。
of object
mrphzbgm6#
接口解决了某种问题。主要功能是......好吧,......定义接口。区分定义和实现。当您要指定或检查类是否支持一组方法时-请使用接口。你不能用任何其他方式做到这一点。(If所有的类都继承自同一个基类,那么抽象类将定义接口。但是当你处理不同的类层次结构时,你需要接口来定义你共有的方法。)
dddzy1tm7#
关于缺点的额外说明:业绩我认为许多人过于轻率地忽视了接口的性能损失。(并不是我不喜欢和不使用接口,但是您应该知道您正在进入的是什么)。接口可能是昂贵的,不仅仅是因为_AddRef / _Release命中(即使你只是返回-1),而且属性必须有一个Get方法。类中的大多数属性具有读访问器的直接访问(例如,属性Prop 1:整数读取FProp 1写入SetProp 1)。改变这种直接方式,对函数调用的无惩罚访问可能会大大降低您的速度(特别是当您开始在循环中添加数十个属性调用时)。例如,使用类的简单循环
for i := 0 to 99 do begin j := (MyClass.Prop1 + MyClass.Prop2 + MyClass.Prop3) / MyClass.Prop4; MyClass.Update; // do something with j end;
当类变成一个接口时,从0个函数调用变成400个函数调用。在那个循环中添加更多的属性,它很快就会变得更糟。你可以用一些技巧来减轻_AddRef / _Release的惩罚(我相信还有其他的技巧,这是我想不起来的):
jaql4c8m8#
我们必须使用接口的唯一情况(除了COM/ActiveX的东西)是当我们需要多重继承,而接口是获得它的唯一途径。在其他几种情况下,当我们尝试使用接口时,我们遇到了各种各样的问题,主要是引用计数(当对象作为类示例和通过接口访问时)。因此,我的建议是,只有当你知道你“需要”它们时才使用它们,而不是当你“认为"它能在某些方面使你的生活更轻松时。更新:正如大卫所提醒的,使用接口,您只能获得接口的多重继承,而不能获得实现的多重继承,但这对我们的需要来说是很好的。
soat7uwm9#
除了其他已经列出的接口之外,接口的一大优点是聚合它们的能力。我写了一篇关于这个主题的博客文章前一段时间,可以在这里找到:http://www.nexusdb.com/support/index.php?q=intf-aggregation(t1;dr:你可以有多个对象,每个对象实现一个接口,然后把它们组装成一个集合,在外界看来,这个集合就像是一个实现所有这些接口的单个对象)您可能还想看看链接到那里的“接口基础”和“高级接口用法和模式”帖子。
9条答案
按热度按时间qmb5sa221#
我现在能想到的就是:
优点:
缺点:
luaexgnf2#
除了这些答案之外,还有一些优势:
1.使用接口来表示行为,并且行为的每个实现都将实现接口。
sd2nnvve3#
我要说的是,没有引用计数的接口在我对 Delphi 的愿望清单上非常高!!!
接口的真实的用途是接口的声明,而不是引用计数的能力!
avkwfej44#
界面有一些微妙的缺点,我不知道人们在使用它们时是否考虑到了:
1.调试变得更加困难。我在调试器中看到过很多奇怪的困难,在步入接口方法调用时。
1.使用接口的糟糕实现会带来一些令人讨厌的代码味道。例如,在定义类的初始具体实现的同一个单元中定义接口,增加了接口的所有权重,而没有真正提供接口用户和实现者之间的适当分离。我知道这不是接口本身的问题,但是对于那些编写基于接口的代码的人来说,这是一个很大的问题。请把你的接口声明放在只有那些接口声明的单元中,避免单元到单元的依赖地狱,因为把你的接口声明放在和你的实现者类相同的单元中。
oymdgrw75#
当我希望具有不同祖先的对象提供一个公共服务时,我通常会使用接口,根据我自己的经验,我能想到的最好的例子是一个名为
IClipboard
的接口:我有一堆从标准VCL控件派生而来的自定义控件,它们都实现了这个接口,当剪贴板操作到达我的一个窗体时,它会查看活动控件是否支持这个接口,如果支持,则调度相应的方法。
对于一个非常简单的接口,你可以用
of object
事件处理器来完成,但是一旦它变得足够复杂,接口就可以很好地工作。事实上,我认为这是一个非常好的类比。使用一个单一of object
事件不适合功能的接口。mrphzbgm6#
接口解决了某种问题。主要功能是......好吧,......定义接口。区分定义和实现。
当您要指定或检查类是否支持一组方法时-请使用接口。
你不能用任何其他方式做到这一点。
(If所有的类都继承自同一个基类,那么抽象类将定义接口。但是当你处理不同的类层次结构时,你需要接口来定义你共有的方法。)
dddzy1tm7#
关于缺点的额外说明:业绩
我认为许多人过于轻率地忽视了接口的性能损失。(并不是我不喜欢和不使用接口,但是您应该知道您正在进入的是什么)。接口可能是昂贵的,不仅仅是因为_AddRef / _Release命中(即使你只是返回-1),而且属性必须有一个Get方法。类中的大多数属性具有读访问器的直接访问(例如,属性Prop 1:整数读取FProp 1写入SetProp 1)。改变这种直接方式,对函数调用的无惩罚访问可能会大大降低您的速度(特别是当您开始在循环中添加数十个属性调用时)。
例如,使用类的简单循环
当类变成一个接口时,从0个函数调用变成400个函数调用。在那个循环中添加更多的属性,它很快就会变得更糟。
你可以用一些技巧来减轻_AddRef / _Release的惩罚(我相信还有其他的技巧,这是我想不起来的):
jaql4c8m8#
我们必须使用接口的唯一情况(除了COM/ActiveX的东西)是当我们需要多重继承,而接口是获得它的唯一途径。在其他几种情况下,当我们尝试使用接口时,我们遇到了各种各样的问题,主要是引用计数(当对象作为类示例和通过接口访问时)。
因此,我的建议是,只有当你知道你“需要”它们时才使用它们,而不是当你“认为"它能在某些方面使你的生活更轻松时。
更新:正如大卫所提醒的,使用接口,您只能获得接口的多重继承,而不能获得实现的多重继承,但这对我们的需要来说是很好的。
soat7uwm9#
除了其他已经列出的接口之外,接口的一大优点是聚合它们的能力。
我写了一篇关于这个主题的博客文章前一段时间,可以在这里找到:http://www.nexusdb.com/support/index.php?q=intf-aggregation(t1;dr:你可以有多个对象,每个对象实现一个接口,然后把它们组装成一个集合,在外界看来,这个集合就像是一个实现所有这些接口的单个对象)
您可能还想看看链接到那里的“接口基础”和“高级接口用法和模式”帖子。