解决方法
假设您使用语言X开发了一个非常棒的框架,并将其作为版本1发布。您的用户可以做到这一点,并且它被大量使用。与成功融合,您决定发布版本2更加惊人。你特别确保它完全向后兼容。突然间,用户开始报告奇怪的行为。他们自己的虚拟方法在奇怪的时候被叫。许多人报告说,他们的旧代码不会用新版本编译。奇怪。所有相同的对象,方法和功能仍然存在。你所做的只是添加一些虚拟方法到一些基类,一些新的对象类型和一些新的可选功能。发生了什么?
覆盖和重新引入指令用于消除此问题,要求为了实际覆盖虚拟方法,必须使用override指令代替虚拟伪指令。如果你碰巧介绍你自己的虚拟方法,它与你祖先的一个虚拟方法有着同样的名字,编译器就会警告你,但仍然会做正确的事情。在这种情况下,使用重新引入,不仅可以抑制该警告,还可以在您打算这样做的源中记录文件。
没有覆盖和重新引入指令,您将无法不断地发展您的框架,而不必担心破坏所有用户。如果您的用户每次发布新版本时都必须进行大量修改,那么他们将不愿采用新版本。最后,使用“override”也允许框架设计者在不破坏用户代码的情况下更改祖先的虚拟类型。例如,在Delphi中,许多方法被标记为“动态”,它是一种基于表的运行时方法查找形式的多态。它的执行速度不如常规虚拟机那么快,因此通常用于很少被覆盖的方法和/或对用户操作的响应,而额外的开销从未被注意到。假设在框架的V1中,方法被标记为“动态”,但实际上它最终被覆盖并被称为比您想要的更多。在V2中,您可以将其更改为“虚拟”,而不用担心用户的代码被破坏。
Delphi的Object Pascal语言不是识别这个问题的唯一语言。完全相同的原因,C#需要使用“覆盖”指令。 C标准委员会终于认识到了这个问题,正在修改语言来支持它。在C中,如果方法的名称和参数列表与祖先的虚拟机匹配,那么它是一个覆盖(即使你不在后代说“虚拟”)。对于即将到来的新C标准,如果指定“虚拟”并且签名不匹配,则它是在当前类上引入的新的虚拟方法。如果与祖先有签名匹配,并且作者没有打算重写,那么“new”关键字用于告诉编译器这是此类的新虚拟机。