如果没有显式调用,Delphi是否调用在覆盖过程中继承的

时间:2020-03-05 18:50:37  来源:igfitidea点击:

如果代码中没有显式调用,Delphi是否会在覆盖的过程中调用继承,即(继承;),我具有以下结构(从超类到子类)

TForm >> TBaseForm >> TAnyOtherForm

项目中的所有表单都将继承自TBaseForm,因为它将具有用于每种表单(安全性,验证等)的所有标准设置和破坏性部分。

TBaseForm的代码具有onCreate和onDestroy过程,但是如果有人(例如我)忘记在TAnyOtherForm上将继承的onCreate添加到onCreate上,Delphi会为我调用吗?我在网上找到了引用,说它不是必需的,但是如果代码中省略了它,则没有地方说它是否被调用。

另外,如果它确实为我调用了继承的功能,什么时候会调用它?

解决方案

回答

不,如果我们将调用留给继承,它将不会被调用。否则,将无法覆盖方法并完全省略其父版本。

回答

必须显式进行继承的调用。通常,在等效情况下(不包括类构造函数),没有语言会自动调用继承的函数。

很容易忘记在类构造函数中进行继承的调用。在这种情况下,如果基类需要初始化任何数据,则我们将发生访问冲突。

也许我们可以在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;

回答

值得一提的是,不调用Destroy中继承的任何对象都可能导致内存泄漏。在源代码中有可用的工具来检查这一点。

回答

正如其他人指出的那样,继承的代码不是隐式调用的。我们必须明确地调用它。这为我们提供了一些有用的灵活性。例如,我们可能想要在继承的代码之前做一些预处理代码,然后再做一些后处理代码。可能看起来像:

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

回答

否。这就是压倒一切的重点。

回答

必须在后代对象以及可视形式继承中显式调用Inherited。如果我们使用类完成,那么如果我们将该定义标记为重写,则它将自动添加继承的内容(但不是为了重新引入)。如果我们使用的是可视表单继承,则当我们通过表单编辑器添加新的事件处理程序时,它也会添加继承的事件处理程序。