2011-07-04 31 views
5
TMyClass = class(TObject) 
private 
    FMyObject: TObject; 
    function GetMyObject: TObject; 
public 
    property MyObject: TObject read GetMyObject write FMyObject; 
end; 

function TMyClass.GetMyObject: TObject; 
begin 
    if FMyObject = nil then 
    FMyObject := TObject.Create; 

    Result := FMyObject; 
end; 

Đôi khi, "MyObject" không được tạo bên trong mà được tạo ra bên ngoài và gán cho tham số. Nếu đối tượng này được tạo ra bên ngoài, tôi không thể giải phóng nó trong ngữ cảnh này.là cách tốt nhất để kiểm soát vòng đời loại đối tượng kiểu trường?

Tôi có nên tạo TList và Thêm vào tất cả các đối tượng đã được tạo bên trong và phá hủy mọi thứ trên trình phá hủy không?

Làm cách nào để kiểm soát tuổi thọ của tham số nếu nó được tạo nội bộ hay không? Những gì bạn đề nghị để làm gì? Có mô hình nào để làm điều này không?

+0

làm thế nào MyObject có thể được tạo ra bên ngoài nếu nó có công cụ sửa đổi truy cập riêng? không có gì expept lớp này nhìn thấy tài sản này – heximal

+1

@heximal: Rất có thể (không phải trong mã ví dụ) bằng cách xây dựng tiêm. – jpfollenius

+1

@heximal: Trường là riêng tư, thuộc tính là công khai và đọc/ghi, tức là nó có thể được sử dụng như 'Obj.MyObject: = TSomeObject.Create;'. – ain

Trả lời

3

Tôi đoán tốt nhất là thiết kế lại mã của bạn để vấn đề này không phát sinh - loại sự mơ hồ về quyền sở hữu này là một mớ hỗn độn.

Dù sao, một tùy chọn sẽ là sử dụng giao diện (tham chiếu được tính). Đây là vấn đề trong trường hợp tham chiếu vòng tròn.

Nếu các đối tượng bên ngoài tạo ra không phải là tài liệu tham khảo chỉ sau đó bạn vẫn có thể tạo ra bản sao nội bộ của đối tượng, một cái gì đó giống như

procedure TMyClass.SetMyObject(const Value: TObject); 
begin 
    MyObject.Assign(Value); 
end; 

Bạn có thể gán đối tượng bên ngoài để lĩnh vực khác với nội bộ và sau đó bạn don' t Free trường đó trong destructor. Hoặc thiết lập một lá cờ trong setter tài sản để bạn biết không để giải phóng các đối tượng bên ngoài ...

+0

+1 Bản sao trên mẫu phân công được sử dụng trong VCL, vì vậy nên quen thuộc với các nhà phát triển Delphi khác, tăng cường khả năng bảo trì. – Nat

+0

@Nat Sao chép vào bài tập là tốt trừ khi bạn thực sự muốn có một tham chiếu đến một đối tượng được chia sẻ. –

7

tôi muốn thiết lập một lá cờ trong tài sản Setter

procedure TMyClass.SetMyObject(AObject: TObject); 
begin 
    if Assigned(MyObject) and FIsMyObject then 
    FMyObject.Free; 
    FIsMyObject := False; 
    FMyObject := AObject; 
end; 

function TMyClass.GetMyObject: TObject; 
begin 
    if FMyObject = nil then 
    begin 
    FMyObject := TObject.Create; 
    FIsMyObject := True; 
    end; 

    Result := FMyObject; 
end; 

Destructor TMyClass.Destroy; 
begin 
    if FIsMyObject then 
     FMyObject.Free; 
end; 
+1

+1 Tôi luôn làm theo cách này. Nó cảm thấy một chút không thích hợp nhưng tôi đã không tìm thấy một thay thế mà tôi thích. –

1

Hai giải pháp hợp lý và thiết thực nhất (giữ một lá cờ, sao chép về chuyển nhượng) đã được đưa ra, nhưng vì lợi ích đầy đủ và vì trường đối tượng không có khả năng thuộc loại Tobject, đây là ba phương pháp tiếp cận khác. Tính thực tiễn của chúng phụ thuộc vào loại trường đối tượng, cho dù bạn thực sự không muốn có thêm cờ boolean và liệu bạn không thích thêm một số hành vi thông minh vào cấu trúc này.

(Cảnh báo: đây có thể là một chút cường điệu.)

  • Kiểm tra nếu lĩnh vực đối tượng là các loại đối tượng riêng của bạn:

    property MyObject: TSomeAncestor read GetMyObject write SetMyObject; 
        end; 
    
    implementation 
    
    type 
        TMyObject = class(TSomeAncestor) ... end; 
    
    destructor TMyClass.Destroy; 
    begin 
        if FMyObject is TMyObject then 
        FMyObject.Free; 
    
  • Thử nghiệm trên quyền sở hữu của trường đối tượng:

    property MyObject: TOwnedObject read GetMyObject write SetMyObject; 
        end; 
    
    implementation 
    
    destructor TMyClass.Destroy; 
    begin 
        if FMyObject.Owner = Self then 
        FMyObject.Free; 
    

    Con này struction đặc biệt hữu ích nếu đối tượng bên ngoài nên được giải phóng bởi lớp này: chỉ cần thiết lập chủ sở hữu của nó cho cá thể lớp này. Quyết định này không còn phụ thuộc vào việc tạo ra bên trong hoặc bên ngoài của đối tượng.

  • Nếu trường đối tượng xuống từ TComponent, thì bạn không phải hoàn toàn miễn phí.

+0

Ah, vâng, quên đề cập đến tùy chọn "kiểm tra chủ sở hữu" ... – ain

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