简体   繁体   English

如果没有显式调用,Delphi调用是否在重写过程上继承

[英]Does Delphi call inherited on overridden procedures if there is no explicit call

Does Delphi call inherited on overridden procedures if there is no explicit call in the code ie (inherited;), I have the following structure (from super to sub class) 如果代码中没有显式调用,Delphi调用是否继承了重写过程,即(继承;),我有以下结构(从超类到子类)

TForm >> TBaseForm >> TAnyOtherForm TForm >> TBaseForm >> TAnyOtherForm

All the forms in the project will be derived from TBaseForm, as this will have all the standard set-up and destructive parts that are used for every form (security, validation ect). 项目中的所有表单都将从TBaseForm派生,因为这将包含用于每种表单的所有标准设置和破坏性部分(安全性,验证等)。

TBaseForm has onCreate and onDestroy procedures with the code to do this, but if someone (ie me) forgot to add inherited to the onCreate on TAnyOtherForm would Delphi call it for me? TBaseForm有onCreate和onDestroy程序,代码可以做到这一点,但如果有人(即我)忘记在TAnyOtherForm上添加继承到onCreate,Delphi会为我调用它吗? I have found references on the web that say it is not required, but nowhere says if it gets called if it is omitted from the code. 我在网上发现了一些说它不是必需的引用,但如果从代码中省略它就会调用它。

Also if it does call inherited for me, when will it call it? 如果它确实为我继承了,它什么时候会调用呢?

No, if you leave the call to inherited away, it will not be called. 不,如果您将呼叫留给继承,则不会被呼叫。 Otherwise it would not be possible to override a method and totally ommit the parent version of it. 否则,将无法覆盖方法并完全省略它的父版本。

The inherited call has to be made explicitly. 必须明确地进行继承的调用。 In general no language automatically calls the inherited function in equivalent situations (class constructors not included). 通常,在相同的情况下,没有语言会自动调用继承的函数(不包括类构造函数)。

It is easy to forget to make the inherited call in a class constructor. 很容易忘记在类构造函数中进行继承调用。 In such a situation if a base class needs to initialize any data you have an access violation waiting to happen. 在这种情况下,如果基类需要初始化任何数据,则会发生等待发生的访问冲突。

Perhaps you could override DoCreate and DoDestory in your TBaseForm class so you could ensure some code is executed regardless of the implementation of child classes. 也许您可以在TBaseForm类中覆盖DoCreate和DoDestory,这样您就可以确保执行某些代码而不管子类的实现。

// interface

TBaseForm = Class(TForm)
...
Protected
    Procedure DoCreate(Sender : TObject); Override;
End

// implementation

Procedure TBaseForm.DoCreate(Sender : TObject);
Begin
    // do work here

    // let parent call the OnCreate property  
    Inherited DoCreate(Sender);
End;

It is worth mentioning that not calling inherited in Destroy of any object can cause memory leaks. 值得一提的是,不在任何对象的Destroy中调用inherited会导致内存泄漏。 There are tools available to check for this in your source code. 您可以在源代码中找到可用于检查此功能的工具。

Inherited must be explicitly called in descendant objects as well as in visual form inheritance. 必须在后代对象以及可视化表单继承中显式调用Inherited。 If you use class completion then it adds inherited automatically if you flagged the definition as override (but not for reintroduce). 如果您使用类完成,那么如果您将定义标记为覆盖(但不是重新引入),则会自动添加继承。 If you are using visual form inheritance then when you add a new event hander through the form editor then it will add inherited as well. 如果您正在使用可视化表单继承,那么当您通过表单编辑器添加新的事件处理程序时,它也将添加继承。

The inherited code is not called implicitly, as the others have indicated. 正如其他人所指出的那样,不会隐式调用继承的代码。 You must call it explicitly. 你必须明确地调用它。 This gives you some useful flexibility. 这为您提供了一些有用的灵活性 For instance, you might want to do some preprocessing code prior to the inherited code, then do some post processing code afterwards. 例如,您可能希望在继承的代码之前执行一些预处理代码,然后再执行一些后处理代码。 This might look like: 这可能看起来像:

procedure TMyCalcObject.SolveForX;
begin
  ResetCalcState;
  inherited SolveForX;
  PostProcessSolveForX;
end;

You must call it explicitly. 你必须明确地调用它。 This allows a lot of flexibility, since you can choose at which point in code to call the inherited method. 这样可以提供很大的灵活性,因为您可以选择代码中的哪一点来调用继承的方法。 But it's also a big source of bugs. 但它也是错误的重要来源。 It's easy to forget to call the inherited function and compiler has no way to tell if you did it deliberately or you just forgot. 很容易忘记调用继承的函数,编译器无法判断你是故意这么做还是忘记了。

There should be some kind of directive "skip_inherited" to tell compiler that you don't want to call the inherited method. 应该有某种指令“skip_inherited”告诉编译器你不想调用继承的方法。

Compiler would then easily report error if it didn't find either "inherited" or "skip_inherited". 如果编译器没有找到“inherited”或“skip_inherited”,则很容易报告错误。 That would mean you forgot. 那意味着你忘记了。 But unfortunately nobody in CodeGear thought of that. 但不幸的是CodeGear中没有人想到这一点。

不,这是压倒一切的重点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM