2009-01-23 21 views
13

Dường như hoàn toàn không liên quan để yêu cầu TComponent làm chủ sở hữu để khởi tạo một đối tượng thuộc loại nào đó. Tại sao có quá nhiều thành phần Delphi yêu cầu điều này?Tại sao một số thành phần Delphi yêu cầu "AOwner: TComponent" để xây dựng chúng?

Ví dụ: TXMLDocument yêu cầu đối tượng TComponent để khởi tạo.

Tại sao điều này và nếu có lý do chính đáng, tôi nên sử dụng điều gì trong đó để "làm đúng"?

Trả lời

35

Thành phần chủ sở hữu được cho là quản lý tất cả các thành phần được sở hữu của nó. Các thành phần được sở hữu sẽ tự động bị hủy khi chủ sở hữu bị hủy.

Điều này giúp nhà phát triển chỉ cần kéo các thành phần từ bảng công cụ, thả chúng vào biểu mẫu và chỉ nối các sự kiện để hoàn thành công việc mà không phải lo lắng về việc quản lý tuổi thọ của các thành phần.

Biểu mẫu là chủ sở hữu của tất cả các thành phần được thả trên đó. Đối tượng Application là chủ sở hữu của biểu mẫu. Khi ứng dụng được đóng, đối tượng Ứng dụng sẽ bị phá hủy, điều này sẽ phá hủy các biểu mẫu và tất cả các thành phần.

Nhưng chủ sở hữu không thực sự cần thiết khi tạo thành phần. Nếu bạn truyền Nil cho tham số, thành phần sẽ được tạo mà không có chủ sở hữu và trong trường hợp này, bạn sẽ chịu trách nhiệm quản lý tuổi thọ của thành phần.

+0

Câu trả lời hay. Vì vậy, nếu tôi muốn quản lý cuộc đời mình, làm thế nào tôi sẽ chắc chắn rằng một đối tượng bị phá hủy khi tôi thực hiện với nó? – Dave

+1

@prapin: Chỉnh sửa nhẹ là cần thiết: Đối tượng Ứng dụng chỉ là chủ sở hữu của biểu mẫu nếu biểu mẫu đã được tạo bằng Application.CreateForm() hoặc khi Ứng dụng được chuyển đến Tạo dưới dạng AOwner. Biểu mẫu có thể được sở hữu bởi một biểu mẫu khác hoặc bất kỳ thành phần nào khác cho vấn đề đó. – mghie

+0

@Dave: Theo dõi các câu hỏi SO đối phó với quyền sở hữu đối tượng: 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

9

Tất cả các con cháu TComponent yêu cầu Chủ sở hữu, nó được định nghĩa trong hàm tạo TComponent. Thành phần chủ sở hữu chịu trách nhiệm hủy tất cả các thành phần được sở hữu.

nếu bạn muốn kiểm soát thời gian hoạt động, bạn có thể chuyển số không thành tham số.

3

Chỉ cần thêm một số thông tin bổ sung.

Mỗi điều khiển cũng có một phụ huynh. (Một TWinControl). Trường hợp chủ sở hữu chăm sóc suốt đời, phụ huynh sẽ chăm sóc hiển thị đối tượng.

Ví dụ: biểu mẫu có bảng điều khiển và bảng điều khiển có nút. Trong trường hợp đó, biểu mẫu sở hữu bảng điều khiển và nút. Nhưng biểu mẫu là phụ huynh của bảng điều khiển và bảng điều khiển là nút cha của nút.

+1

Có, nhưng không phải tất cả các thành phần (TComponent) đều là các điều khiển (TControl). TControl xuống từ TComponent. Một thành phần không phải là một điều khiển không có một phụ huynh. –

+0

Cũng đáng chú ý là nếu bạn phá hủy một phụ huynh, trẻ em cũng sẽ bị phá hủy, ngay cả khi chúng không thuộc quyền sở hữu của phụ huynh. –

3

Ngoài ra còn có một số thứ khác cần lưu ý. Tôi đã sử dụng nhiều hơn một vài thành phần của bên thứ ba mà dựa trên một thành phần chủ sở hữu được thông qua trong việc tạo ra constructor, và nếu bạn vượt qua trong Nil sẽ ném một ngoại lệ/AV.

Kết quả là các thành phần này sẽ hoạt động tốt khi bạn sử dụng trực quan trong IDE nhưng gây ra sự cố khi chúng được tạo tại thời gian chạy.

Nguyên nhân của những vấn đề này, theo nghĩa nào đó, thiết kế xấu. Không có gì trong trạng thái quy tắc bạn không thể/không được chuyển vào NIL như tham số aOwner.

1

Đối tượng không YÊU CẦU một tComponent được chuyển thành AOwner. Bạn có thể dễ dàng vượt qua nil này và xử lý sự hủy diệt chính mình. Thông thường, tôi có xu hướng sử dụng kỹ thuật này cho các thói quen được bản địa hóa trong đó thành phần được sử dụng sẽ không được sử dụng bên ngoài phương thức hiện tại.ví dụ:

Procedure TForm1.Foo; 
var 
    XmlDoc : tXmlDocument; 
begin 
    XmlDoc := tXmlDocument.Create(nil); 
    try 
    // do processing of the XMLDoc here 
    finally 
    FreeAndNil(XmlDoc); 
    end; 
end; 
+2

'TXMLDocument' là trường hợp đặc biệt. Khi bạn truyền một chủ nhân 'nil' cho hàm tạo của nó, đối tượng này hoạt động như một giao diện được tính tham chiếu, không phải là một thành phần! Như vậy, bạn ** PHẢI ** gán đối tượng cho biến giao diện 'IXMLDocument' để duy trì chính xác số tham chiếu đó. Hành vi này được ghi lại trong Trợ giúp. Vì bạn phải sử dụng 'IXMLDocument' trong trường hợp đó, bạn nên sử dụng' NewXMLDocument() 'và các hàm liên quan thay vì instantiating' TXMLDocument' theo cách thủ công. –

0

Bạn shoudl sử dụng này vì hai lý do: - cơ chế sở hữu cũng đứng như một loại rác hệ thống thu - cơ chế sở hữu là rất quan trọng trong quá trình serialization Delphi (Stream.ReadComponent/WriteComponent vv).

0

Thông số chủ sở hữu chỉ cần thiết đối với TComponent con cháu, vì nó là tham số của hàm tạo TComponent. Tất cả các thành phần có thể truy cập tại thời điểm thiết kế để rơi vào các lớp TForm, TFrameTDataModuleTComponent hậu duệ (bao gồm TXMLDocument).

Các vấn đề liên quan