要求TComponent作为所有者实例化某种对象似乎完全不相干。为什么需要这么多的Delphi组件?为什么一些Delphi组件需要“AOwner:TComponent”来构建它们?
例如,TXMLDocument需要一个TComponent对象来实例化。
为什么会这样,如果有充分的理由,我应该用什么来“做正确的事情”?
要求TComponent作为所有者实例化某种对象似乎完全不相干。为什么需要这么多的Delphi组件?为什么一些Delphi组件需要“AOwner:TComponent”来构建它们?
例如,TXMLDocument需要一个TComponent对象来实例化。
为什么会这样,如果有充分的理由,我应该用什么来“做正确的事情”?
拥有者组件应该管理其拥有的所有组件。当拥有者被销毁时,拥有的组件会自动销毁。
这有助于开发人员从工具选项板拖动组件,将它们放在窗体上,只需将事件挂钩即可完成工作,而无需担心管理组件的生命周期。
表单是所有组件的所有者。 Application对象是表单的所有者。当应用程序关闭时,应用程序对象被销毁,从而破坏表单和所有组件。
但是,创建组件时,所有者并不是真正需要的。如果您将Nil传递给参数,则组件将在没有所有者的情况下创建,在这种情况下,您有责任管理组件的生命周期。
所有TComponent后代都需要Owner,它在TComponent的构造函数中定义。 所有者组件负责销毁所有拥有的组件。
如果要控制生命期,可以将nil作为参数传递。
只是添加一些额外的信息。
每个控件也有一个父项。 (一个TWinControl)。如果业主照顾一生,则家长负责展示该物品。
例如,窗体有一个面板,面板上有一个按钮。在这种情况下,表单拥有面板和按钮。但窗体是面板的父窗体,面板是按钮的父窗体。
还有其他东西需要注意。我已经使用了多个第三方组件,其中依赖在构造函数创建中传递的所有者组件,并且如果传递给无,则会抛出异常/ AV。
最终的结果是,这些组件在IDE中直观使用时可以正常工作,但在运行时创建时会造成问题。
从某种意义上说,这些问题的原因是糟糕的设计。作为aOwner参数,规则中没有任何内容不能/不应传递NIL。
对象不是需要 tComponent将作为AOwner传递。你可以轻松地将nil传递给它并自己处理破坏。大多数情况下,我倾向于将此技术用于本地化例程,其中正在使用的组件不会在当前方法之外使用。例如:
Procedure TForm1.Foo;
var
XmlDoc : tXmlDocument;
begin
XmlDoc := tXmlDocument.Create(nil);
try
// do processing of the XMLDoc here
finally
FreeAndNil(XmlDoc);
end;
end;
您shoudl使用的原因有两个: - 所有权机制也代表作为一种垃圾收集系统 的 - 所有权机制是德尔福序列化过程(Stream.ReadComponent/WriteComponent等重要)。
只有TComponent
后代需要Owner参数,因为它是TComponent
构造函数的参数。在设计时可以访问的所有组件在TForm
,TFrame
和TDataModule
类别上是TComponent
后代(其包括TXMLDocument
)。
很棒的回答。所以,如果我想自己管理一生,当我完成它时,如何确保一个对象被破坏? – Dave 2009-01-24 11:07:18
@prapin:稍微修正是必要的:如果已使用Application.CreateForm()创建表单或者已将应用程序传递给创建为AOwner,则Application对象只是表单的所有者。表单可以由其他表单或其他任何组件拥有。 – mghie 2009-01-24 11:41:57
@Dave:遵循SO问题处理对象所有权:http://stackoverflow.com/questions/398137/what-is-the-best-way-to-do-nested-try-and-finally-statement-in- delphi#399860,http://stackoverflow.com/questions/415958/how-to-automatically-free-classes-objects#415990 – mghie 2009-01-24 11:43:54