Quello che sta accadendo qui è che chiami TContainer.Create
e crei un'istanza in un oggetto. Ma poi assegni quell'istanza a un riferimento all'interfaccia, la variabile globale Foo
. Poiché tale variabile è di tipo IFoo
, la delega dell'interfaccia indica che l'oggetto di implementazione è l'istanza di TFooImpl
e non l'istanza di TContainer
.
Quindi niente prende mai un riferimento all'istanza di TContainer
, il suo conteggio di riferimenti non viene mai aumentato e quindi non viene mai distrutto.
Non penso che ci sia un modo molto semplice per aggirare questo. Potresti essere in grado di utilizzare TAggregatedObject
ma potrebbe non risolvere il tuo problema. Ti costringerebbe a dichiarare TContainer.FFoo
di tipo TFooImpl
che immagino tu non voglia fare. In ogni caso, ecco come appare rifusione in questo modo:
program SO16210993_TAggregatedObject;
{$APPTYPE CONSOLE}
type
IFoo = interface
procedure Foo;
end;
TFooImpl = class(TAggregatedObject, IFoo)
procedure Foo;
end;
TContainer = class(TInterfacedObject, IFoo)
private
FFoo: TFooImpl;
function GetFoo: IFoo;
public
destructor Destroy; override;
property Foo: IFoo read GetFoo implements IFoo;
end;
procedure TFooImpl.Foo;
begin
Writeln('TFooImpl.Foo called');
end;
destructor TContainer.Destroy;
begin
Writeln('TContainer.Destroy called');//this line does run
FFoo.Free;
inherited;
end;
function TContainer.GetFoo: IFoo;
begin
if not Assigned(FFoo) then
FFoo := TFooImpl.Create(Self);
Result := FFoo;
end;
procedure Main;
var
Foo : IFoo;
begin
Foo := TContainer.Create;
Foo.Foo;
end;
begin
Main;
Readln;
end.
Il documentation vuol parlare di questo:
La classe si utilizza per implementare l'interfaccia delegato dovrebbe derivare da TAggregationObject.
Inizialmente non sono riuscito a trovare alcuna documentazione per questo TAggregationObject
. E alla fine ho capito che in realtà si chiama TAggregatedObject
ed è documented.
TAggregatedObject fornisce la funzionalità di un oggetto interno di un aggregato implementando metodi IInterface delegare alla controllo IInterface.
Un oggetto aggregato è un oggetto composto da diversi oggetti interfacciati . Ogni oggetto implementa il proprio comportamento e le proprie interfacce, ma tutti gli oggetti condividono lo stesso conteggio dei riferimenti, che è quello dell'oggetto controller . Nel modello contenitore, il controller è l'oggetto contenitore .
TAggregatedObject non supporta le interfacce. Tuttavia, poiché è tipico di un aggregato, implementa i metodi di IInterface, che vengono utilizzati dagli oggetti che discendono da esso. TAggregatedObject, pertanto, funge da base per le classi che implementano le interfacce per creare oggetti che fanno parte di un aggregato .
TAggregatedObject viene utilizzato come base per le classi che creano oggetti contenuti e oggetti di connessione.L'utilizzo di TAggregatedObject garantisce che le chiamate vengano delegate all'Interface di controllo dell'aggregato.
Il IInterface di controllo è specificato nel costruttore per TAggregatedObject ed è indicato dalla proprietà Controller.
Inoltre c'è questa dai commenti del codice sorgente:
TAggregatedObject e TContainedObject sono classi base adatti per gli oggetti interfacciati destinati ad essere aggregate o contenuta in un oggetto esterno controllo . Quando si utilizza la sintassi "implements" su una proprietà di interfaccia in una dichiarazione di classe dell'oggetto esterno, utilizzare questi tipi per implementare l'oggetto interno.
Le interfacce implementate da oggetti aggregati per conto del controller non devono essere distinguibili dalle altre interfacce fornite dal controller. Gli oggetti aggregati non devono mantenere il numero di riferimento - devono avere la stessa durata del controller . Per ottenere ciò, gli oggetti aggregati riflettono i metodi di conteggio dei riferimenti sul controller.
TAggregatedObject riflette semplicemente le chiamate di QueryInterface al suo controller . Da tale oggetto aggregato, è possibile ottenere qualsiasi interfaccia supportata dal controller e solo le interfacce supportate dal controller . Ciò è utile per l'implementazione di una classe del controller che utilizza uno o più oggetti interni per implementare le interfacce dichiarate sulla classe controller. Aggregation promuove la condivisione dell'implementazione attraverso la gerarchia degli oggetti.
TAggregatedObject è ciò che la maggior parte degli oggetti aggregati deve ereditare da , soprattutto se utilizzato in combinazione con la sintassi "implements" .
"Mi manca qualcosa?" Non lo so. Ma certamente lo siamo. Hai dimenticato di includere il codice! È richiesto un programma completo che mostri il comportamento. Altrimenti dobbiamo indovinare. –
hai alcuni riferimenti extra o loop di riferimento. Aggiungi sostituzioni per TFirstSecond._AddRef e TFirstSecond._Release e inserisci i punti di interruzione qui, ottieni un elenco completo di riferimenti e vedi quali non sono stati cancellati –
Bene, il problema è che le tue interfacce sono delegate. Non sono sicuro perché questo causa questo comportamento. –