2013-03-04 9 views
9

Mam nadzieję stworzyć coś w rodzaju „TOwnedStringList” (nazwa klasy jest fikcją), że mogę zbudować jako:Jak utworzyć potomka TStringList z właścicielem, który automatycznie zwolni TStringList?

sl := TOwnedStringList.Create(Self); 
sl.Sorted := True; 
sl.Duplicates := dupIgnore; 
sl.Add(...); 
// etc... 

Gdzie Self mogłaby być formą (na przykład), tak, że właściciel automatycznie usuń StringList. Chcę móc samodzielnie dzwonić pod numer sl.Free.

Czy to możliwe?

Odpowiedz

13

To będzie trochę brudny. Musiałbyś zrobić coś takiego.

type 
    TOwnerComponent = class(TComponent) 
    private 
    FOwnedObject: TObject; 
    public 
    constructor Create(Owner: TComponent; OwnedObject: TObject); 
    destructor Destroy; override; 
    end; 

    TOwnedStringList = class(TStringList) 
    private 
    FOwner: TOwnerComponent; 
    public 
    constructor Create(Owner: TComponent); 
    destructor Destroy; override; 
    end; 

{ TOwnerComponent } 

constructor TOwnerComponent.Create(Owner: TComponent; OwnedObject: TObject); 
begin 
    inherited Create(Owner); 
    FOwnedObject := OwnedObject; 
end; 

destructor TOwnerComponent.Destroy; 
begin 
    FOwnedObject.Free; 
    inherited; 
end; 

{ TOwnedStringList } 

constructor TOwnedStringList.Create(Owner: TComponent); 
begin 
    inherited Create; 
    if Assigned(Owner) then 
    FOwner := TOwnerComponent.Create(Owner, Self); 
end; 

destructor TOwnedStringList.Destroy; 
begin 
    if Assigned(FOwner) and not (csDestroying in FOwner.ComponentState) then 
    begin 
    FOwner.FOwnedObject := nil; 
    FOwner.Free; 
    end; 
    inherited; 
end; 

Zasadniczo utworzyć instancję TOwnerComponent który jest własnością Owner które przechodzą do TOwnedStringList.Create. Kiedy ten Owner umiera, niszczy on TOwnerComponent, który z kolei niszczy twoją listę ciągów.

Kod jest odporny na jawne wywołanie Free na liście ciągów.

+0

+1 Ta sama sztuczka co w przypadku interfejsów w rekordach – jpfollenius

+1

Wygląda obiecująco. Czy konstruktor TOwnerComponent powinien być utworzony z dyrektywą 'reintroduce'? Ponadto, Jak mogę chronić 'TOwnedStringList' przed' sl.Create (zero) 'i jawne' sl.Free'? – ZigiZ

+1

'Utwórz (zero)' jest w porządku. To znaczy, nie ma właściciela, pozwól mi przejąć odpowiedzialność za własność. Lub jeśli tego nie chcesz, wtedy podnieś wyjątek. Wyraźny "Wolny" wymaga nieco więcej myślenia. Niedźwiedź ze mną. –