2011-07-04 3 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 :이 필드는 private이며 속성은 public이고 읽기/쓰기가 가능합니다. 즉 Obj.MyObject : = TSomeObject.Create;와 같이 사용할 수 있습니다. – ain

답변

3

이 문제가 발생하지 않도록 코드를 다시 디자인하는 것이 가장 좋습니다. 이런 종류의 소유권은 혼란입니다.

어쨌든, 한 가지 옵션은 (참조 계산 된) 인터페이스를 사용하는 것입니다. 순환 참조의 경우 문제가됩니다.

외부에서 생성 된 객체가 유일한 참조를하지해야하는 경우가 여전히 객체의 내부 복사, 당신은 내부의 다른 분야에 외부 개체를 할당 할 수

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

같은 것을 만들 수 있습니다 다음은 '돈 t Free 해당 필드가 소멸자에 있습니다. 당신이 알지 못하는 외부 개체를 해제하도록 또는

+0

+1 VCL에서 할당 패턴의 복사본을 사용하므로 다른 델파이 개발자들에게 익숙해야하므로 유지 보수성이 향상됩니다. – 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 유형이 될 가능성이 없기 때문에 다음 세 가지 접근 방식이 있습니다. 이러한 실용성은 객체 필드의 유형에 따라 달라집니다. 실제로 추가 불린 플래그를 원하지 않는지 여부와이 지형에 지능적인 동작을 추가하는 것을 싫어하는지 여부에 따라 다릅니다.

(경고 :이 조금 억지 할 수있다.)

  • 테스트 오브젝트 필드는 개인 객체 타입 인 경우의 소유권에

    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; 
    

    struction은 외부 객체를이 클래스에서 해제해야하는 경우 특히 유용합니다. 소유자 만이 클래스 인스턴스로 설정하면됩니다. 결정은 더 이상 객체의 내부 또는 외부 생성에 의존하지 않습니다.

  • 개체 필드가 ​​TComponent에서 비롯된 경우 전혀 사용하지 않아도됩니다.

+0

아, 네, "소유자 테스트"옵션을 언급하는 것을 잊어 버렸습니다 ... – ain

관련 문제