要求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