reintroduce
在Delphi 中使用关键字的动机是什么?
如果您的子类包含与父类中的虚函数同名的函数,并且未使用override修饰符声明它,则它是编译错误.在这种情况下添加reintroduce修饰符可以修复错误,但我从未理解编译错误的原因.
如果在后代类中声明一个与祖先类中的方法同名的方法,那么您将隐藏该祖先方法 - 这意味着如果您有该后代类的实例(被引用为该类)那么您将没有得到祖先的行为.当祖先的方法是虚拟的或动态的时,编译器会给你一个警告.
现在,您有两种选择之一来抑制该警告消息:
添加关键字reintroduce只会告诉编译器您知道您正在隐藏该方法并且它会抑制警告.您仍然可以在该后代方法的实现中使用inherited关键字来调用祖先方法.
如果祖先的方法是虚拟的或动态的,那么你可以使用覆盖.它具有以下附加行为:如果通过祖先类型的表达式访问此后代对象,则对该方法的调用仍将是后代方法(然后可以选择通过继承来调用祖先).
因此,覆盖和重新引入之间的区别在于多态性.通过重新引入,如果将后代对象转换为父类型,则调用该方法将获得祖先方法,但如果您访问后代类型,则将获得后代的行为.通过覆盖,你总是得到后代.如果祖先方法既不是虚拟方法也不是动态方法,则重新引入不适用,因为该行为是隐式的.(实际上你可以使用一个类助手,但我们现在不会去那里.)
尽管马拉奇说过,你仍然可以在重新引入的方法中调用继承,即使父母既不虚拟也不动态.
本质上重新引入就像覆盖一样,但它适用于非动态和非虚拟方法,并且如果通过祖先类型的表达式访问对象实例,它不会替换行为.
进一步说明:
重新引入是一种向编译器传达意图的方法,您没有犯错误.我们使用override关键字覆盖祖先中的方法,但它要求祖先方法是虚拟的或动态的,并且您希望在作为祖先类访问对象时更改行为.现在进入重新介绍.它允许您告诉编译器您不会意外地创建一个与虚拟或动态祖先方法同名的方法(如果编译器没有警告您,这会很烦人).
那里有许多你为什么隐藏一个编译器,可以让一个成员函数的答案默默是一个坏主意.但是没有现代编译器会默默隐藏成员函数.即使在允许这样做的C++中,总会有一个关于它的警告,这应该足够了.
那么为什么需要"重新引入"呢?主要原因是,当您不再查看编译器警告时,这种错误实际上可能会出现.例如,假设您继承自TComponent,Delphi设计人员为TComponent添加了一个新的虚函数.坏消息是你的派生组件,你在五年前写的并分发给其他人,已经有了一个具有该名称的函数.
如果编译器刚接受了这种情况,某些最终用户可能会重新编译您的组件,请忽略该警告.奇怪的事情会发生,你会受到指责.这要求他们明确接受该函数不是同一个函数.