为啥某些 Delphi 组件需要“AOwner: TComponent”来构造它们?

Posted

技术标签:

【中文标题】为啥某些 Delphi 组件需要“AOwner: TComponent”来构造它们?【英文标题】:Why Do Some Delphi Components Require "AOwner: TComponent" To Construct Them?为什么某些 Delphi 组件需要“AOwner: TComponent”来构造它们? 【发布时间】:2010-10-03 05:34:53 【问题描述】:

要求 TComponent 作为所有者来实例化某种对象似乎完全无关紧要。为什么有这么多 Delphi 组件需要这个?

例如,TXMLDocument 需要一个 TComponent 对象来实例化。

为什么会这样?如果有充分的理由,我应该在其中使用什么来“做正确的事”?

【问题讨论】:

【参考方案1】:

所有者组件应该管理其所有拥有的组件。当所有者被销毁时,拥有的组件会自动销毁。

这有助于开发人员从工具面板中拖出组件,将它们放到表单上,然后连接事件以完成工作,而无需担心管理组件的生命周期。

表单是放置在其上的所有组件的所有者。 Application 对象是表单的所有者。当应用程序关闭时,Application 对象被销毁,进而销毁表单和所有组件。

但是当一个组件被创建时,所有者并不是真正需要的。如果您将 Nil 传递给参数,则将在没有所有者的情况下创建组件,在这种情况下,您将负责管理组件的生命周期。

【讨论】:

很好的答案。所以如果我想自己管理生命周期,我如何确保一个对象在我完成后被销毁? @prapin:需要稍加修正:如果表单是使用 Application.CreateForm() 创建的,或者当 Application 已作为 AOWner 传递给 Create 时,Application 对象才是表单的所有者。一个表单可以由另一个表单或任何其他组件拥有。 @Dave:以下 SO 问题涉及对象所有权:***.com/questions/398137/…、***.com/questions/415958/…【参考方案2】:

所有 TComponent 后代都需要 Owner,它在 TComponent 构造函数中定义。 Owner 组件负责销毁所有 Owned 组件。

如果你想控制生命周期,你可以传递 nil 作为参数。

【讨论】:

【参考方案3】:

只是添加一些额外的信息。

每个控件也有一个父控件。 (一个 TWinControl)。所有者负责生命周期,而父对象负责显示对象。

例如,一个表单有一个面板,而该面板有一个按钮。在这种情况下,表单拥有面板和按钮。但是表单是面板的父级,面板是按钮的父级。

【讨论】:

是的,但不是所有的组件(TComponent)都是控件(TControl)。 TControl 继承自 TComponent。不是控件的组件没有父组件。 另外值得注意的是,如果你销毁了一个父级,子级也会被销毁,即使它们不属于父级。【参考方案4】:

还有其他需要注意的地方。我已经使用了多个第三方组件,它们依赖在构造函数创建中传递的 Owner 组件,如果你传入 Nil 将引发异常/AV。

最终结果是,当您在 IDE 中使用可视化组件时,这些组件可以正常工作,但在运行时创建它们时会出现问题。

从某种意义上说,这些问题的原因是糟糕的设计。规则中没有任何内容表明您不能/不应该将 NIL 作为 aOwner 参数传递。

【讨论】:

【参考方案5】:

您应该使用它有两个原因: - 所有权机制也是一种垃圾收集系统 - 所有权机制在Delphi序列化过程中很重要(Stream.ReadComponent/WriteComponent等)。

【讨论】:

【参考方案6】:

TComponent 后代需要 Owner 参数,因为它是 TComponent 构造函数的参数。在设计时可访问的所有组件都可以放在TFormTFrameTDataModule 类上是TComponent 后代(包括TXMLDocument)。

【讨论】:

以上是关于为啥某些 Delphi 组件需要“AOwner: TComponent”来构造它们?的主要内容,如果未能解决你的问题,请参考以下文章

Delphi - 为啥我不能在 64 位中安装我的组件?

Delphi调试器窗口中为啥变量内容显示不全

可堆叠面板 Delphi 组件

Delphi:比较两个组件之间的属性

为啥我在 IDE 中有另一个尺寸的组件?

为啥我在delphi安装了第三方控件却不能用?