Delphi中的reintroduce和override指令的含义是什么?

Moh*_*mad 27 delphi overriding

overridereintroduce指令有什么区别?什么时候不应该inherited在重写方法中使用关键字?

All*_*uer 46

对Jim的答案的引用,这是非常好的BTW,只描述了使用指令的时间和地点.答案的另一部分是他们为什么还需要?没有它们,许多语言相处得很好,对吗?在设计Delphi Object Pascal语言的各个方面时,OOP(面向对象编程)已经成为主流多年.在此期间,观察到使用许多采用这些概念的语言(Turbo Pascal,C++等)来开发应用程序框架时,我所谓的"版本2"问题.

假设您使用语言X开发了一个很棒的框架,并将其作为版本1发布.您的用户竭尽所能,并且它被大量使用.刷新成功,你决定发布版本2更加棒极了.您特别确保它完全向后兼容.突然,您的用户开始报告奇怪的行为.他们自己的虚拟方法在奇怪的时候被调用.许多人报告他们的旧代码无法使用新版本进行编译.奇怪.所有相同的对象,方法和功能仍然存在.您所做的只是为一些基类,一些新对象类型和一些新的可选功能添加一些虚方法.发生了什么?

覆盖和重新引入指令通过要求为了实际覆盖虚方法而必须使用override指令代替virtual指令来消除此问题.如果您碰巧引入了自己的虚拟方法,该方法与您的祖先的一个虚拟方法具有相同的名称,编译器现在会警告您,但仍然会做正确的事情.在这种情况下,使用重新引入,不仅可以抑制该警告,还可以在您打算执行此操作的源文档中进行记录.

如果没有覆盖和重新引入指令,您将无法继续改进框架而不必担心会破坏所有用户.如果您的用户每次发布新版本时都必须进行大量修改,那么他们就不愿意采用新版本.最后,使用"覆盖"还允许框架设计者在不破坏用户代码的情况下更改祖先中的虚拟类型.例如,在Delphi中,许多方法都标记为"动态",这是一种基于表的运行时方法查找形式的多态性.它的执行速度不如普通虚拟机快,因此它通常用于很少被覆盖的方法和/或对用户操作的响应,其中额外的开销从未被注意到.假设在框架的V1中,一个方法被标记为"动态",但在实践中它最终被覆盖并被调用超出您的预期.在V2中,您可以将其更改为"虚拟",而不必担心用户代码被破坏.

Delphi的Object Pascal语言不是识别此问题的唯一语言.出于完全相同的原因,C#需要使用"override"指令.C++标准委员会终于认识到了这个问题,正在修改语言以支持它......有点儿.在C++中,如果方法的名称和参数列表与祖先的虚拟匹配,则它是一个覆盖(即使你没有在后代上说"虚拟"!).对于即将推出的新C++标准,如果指定"虚拟"且签名不匹配,则它是当前类引入的新虚拟方法.如果存在与祖先的签名匹配且编写者打算覆盖,则使用"new"关键字告诉编译器这是该类的虚拟.


Ces*_*ero 11

重写指令用于覆盖在继承类的虚方法.

再引入指令用于声明具有相同名称的方法,如超类,但具有不同的参数.

  • 仅当超类中的方法(具有相同参数)是虚拟的时才需要重新引入.如果它不是虚拟的,则不需要"重新引入",因为无论如何都会隐藏超类的方法. (6认同)

Tob*_*len 6

什么时候不应该在重写方法中使用inherited关键字?

基本上,答案是当您不希望继承的方法执行时.但要小心,因为不允许继承的方法运行可能会以不合需要的方式破坏继承对象的功能,因此请确保您没有引入任何意外的副作用.

例如,假设您希望完全覆盖名为ApplyDiscount的继承函数,但有人已将折扣百分比硬编码到祖先类中.如果您调用继承的ApplyDiscount,它将覆盖您的代码或计算您将覆盖的值; 在这种情况下,你可以不调用继承并自己应用折扣.

(这是一个人为的例子,所以如果有人能想到更好的一个,请加上它.)