Ответ 1
Здесь происходит то, что вы вызываете TContainer.Create
и создаете экземпляр для объекта. Но вы присваиваете этому экземпляру ссылку на интерфейс, глобальную переменную Foo
. Поскольку эта переменная имеет тип IFoo
, делегирование интерфейса означает, что объект-реализация является экземпляром TFooImpl
и not экземпляра TContainer
.
Следовательно, ничто никогда не ссылается на экземпляр TContainer
, его счетчик ссылок никогда не увеличивается, и поэтому он никогда не уничтожается.
Я не думаю, что это очень простой способ. Вы можете использовать TAggregatedObject
, но это может не решить вашу проблему. Это заставит вас объявить TContainer.FFoo
типом TFooImpl
, который, я думаю, вы не хотите делать. Во всяком случае, вот что это похоже на повторное использование этого способа:
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.
В документации говорится об этом:
Класс, который вы используете для реализации делегированного интерфейса, должен выводиться из объекта TAggregationObject.
Изначально я не мог найти документацию для этого TAggregationObject
. И, наконец, я понял, что он на самом деле назван TAggregatedObject
и документирован.
TAggregatedObject предоставляет функциональные возможности для внутреннего объекта совокупность путем внедрения методов IIterterface для делегирования управляющий IInterface.
Агрегированный объект - это объект, состоящий из нескольких сопряженных объекты. Каждый объект реализует свое поведение и интерфейсы, но все объекты имеют один и тот же счетчик ссылок, который совпадает с объект контроллера. В шаблоне контейнера контроллер является контейнерный объект.
TAggregatedObject сам не поддерживает никаких интерфейсов. Однако, поскольку является типичным для совокупности, он реализует методы IInterface, которые используются объектами, которые опускаются от него. Таким образом, TAggregatedObject служит базой для классов, которые реализовать интерфейсы для создания объектов, которые являются частью агрегат.
TAggregatedObject используется как основа для классов, которые создают объектов и соединительных объектов. Использование TAggregatedObject гарантирует, что обращается к делегату метода IInterface с управляющим интерфейсом IInterface от совокупности.
Управляющий IInterface указан в конструкторе для TAggregatedObject и указывается свойством Controller.
Кроме того, это из комментариев исходного кода:
TAggregatedObject и TContainedObject являются подходящими базовыми классами для сопряженных объектов, предназначенных для агрегирования или содержащихся в внешний управляющий объект. При использовании синтаксиса "реализует" на интерфейса в объявлении класса внешнего объекта, используйте эти типы для реализации внутреннего объекта.
Интерфейсы, реализованные агрегированными объектами от имени контроллер не должен отличаться от других интерфейсов предоставляемый контроллером. Агрегированные объекты не должны поддерживать их собственный счетчик ссылок - они должны иметь одинаковую продолжительность жизни их контроллер. Для этого агрегированные объекты отражают методы подсчета ссылок на контроллер.
TAggregatedObject просто отражает вызовы QueryInterface для его контроллер. Из такого агрегированного объекта можно получить любой интерфейс, поддерживаемый контроллером, и только интерфейсы, которые контроллер поддерживает. Это полезно для реализации контроллера класс, который использует один или несколько внутренних объектов для реализации интерфейсы, объявленные в классе контроллера. Агрегация способствует совместное использование реализации по иерархии объектов.
TAggregatedObject - это то, что наследует большинство совокупных объектов от, особенно при использовании в сочетании с "орудиями", синтаксис.