2011-07-04 10 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; 

「MyObject」は内部的には作成されず、外部で作成されてパラメータに割り当てられることがあります。このオブジェクトが外部で作成されている場合、私はこのコンテキストでそれを解放することはできません。これはオブジェクトフィールドタイプのライフサイクルを制御する最良の方法ですか?

内部で作成されたすべてのオブジェクトにTListとAddを作成し、デストラクタのすべてを破棄する必要がありますか?

パラメータが内部で作成されたかどうかを制御するにはどうすればよいですか?あなたは何をすることを提案しますか?これを行うパターンはありますか?

+0

プライベートアクセス修飾子がある場合、MyObjectは外部からどのように作成できますか?このクラスは何も対象外です。 – heximal

+1

@heximal:コンストラクタインジェクションによる可能性が最も高い(例コードではない) – jpfollenius

+1

@heximal:フィールドはプライベートで、プロパティはpublicで読み書き可能です。つまり、 'Obj.MyObject:= TSomeObject.Create; 'のように使用できます。 – ain

答えて

3

この問題が発生しないように、コードを再設計するのが最良だと思います。この種の所有権のあいまいさは混乱です。

とにかく、1つのオプションは(参照カウントされた)インターフェイスを使用することです。これは循環参照の場合に問題となる。

外部で作成されたオブジェクトは、参照のみであってはならないなら、あなたはまだ「あなたは内部よりも、別のフィールドに外部オブジェクトを割り当てることができ、その後、あなたはドン、

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

のようなものをオブジェクトの内部コピーを作成することができますt Freeそのフィールドはデストラクタにあります。あなたが知らない外部のオブジェクトを解放するように、または

+0

+1 VCLでは割り当てパターンのコピーが使用されているため、他のDelphi開発者にはよく知られているため、保守性が向上します。 – Nat

+0

共有オブジェクトへの参照が実際に必要な場合を除き、割り当て時の@Nat Copyは問題ありません。 –

7

私は(プロパティセッター

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私はいつもこのようにしています。ちょっと気分が悪いと感じますが、私が好む選択肢は見つかりませんでした。 –

1

二つの最も論理的かつ現実的な解決策をにフラグを設定したい...プロパティのセッターにフラグを設定フラグを保持、代入時にコピー)は既に与えられていますが、完全性のためにオブジェクトフィールドはTObject型ではない可能性が高いため、ここでは3つのアプローチがあります。これらの実用性は、実際に余分なブール値フラグを必要としないかどうか、そしてあなたがこの構築にいくつかのインテリジェントな振る舞いを追加することを嫌っているかどうか、オブジェクトフィールドのタイプに依存します。

(警告:これはちょっとこじつけでもよい)

  • テストオブジェクトフィールドには、プライベートオブジェクトの型である場合:の所有権の

    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; 
    
  • テストオブジェクトフィールド:

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

    このコンこのクラスによって外部オブジェクトを解放する必要がある場合は、特に便利です。所有者をこのクラスインスタンスに設定するだけです。この決定は、オブジェクトの内部または外部の作成に依存しなくなりました。

  • オブジェクトフィールドがTComponentから降りた場合、自由に使用する必要はありません。

+0

ああ、はい、 "所有者テスト"オプションを言うのを忘れた... – ain

関連する問題