Delphi interface implements -


i expect reference counting should work on outer aggregating object in interface implementation. if can refer example: clarity in classes implementing multiple interfaces (alternative delegation):

here minimal reproduction of behaviour:

program so16210993;  {$apptype console}  type   ifoo = interface     procedure foo;   end;    tfooimpl = class(tinterfacedobject, ifoo)     procedure foo;   end;    tcontainer = class(tinterfacedobject, ifoo)   private     ffoo: ifoo;   public     constructor create;     destructor destroy; override;     property foo: ifoo read ffoo implements ifoo;   end;  procedure tfooimpl.foo; begin   writeln('tfooimpl.foo called'); end;  constructor tcontainer.create; begin   inherited;   ffoo := tfooimpl.create; end;  destructor tcontainer.destroy; begin   writeln('tcontainer.destroy called');//this line never runs   inherited; end;  procedure main; var   foo : ifoo; begin   foo := tcontainer.create;   foo.foo; end;  begin   main;   readln; end. 

if instead of using implements, implement interface in timplementor class destructor runs.

what happening here call tcontainer.create , create instance object. assign instance interface reference, global variable foo. because variable of type ifoo, interface delegation means implementing object instance of tfooimpl , not instance of tcontainer.

hence nothing ever takes reference instance of tcontainer, reference count never increased, , never destroyed.

i don't think there's easy way around this. may able use taggregatedobject may not solve problem. force declare tcontainer.ffoo of type tfooimpl imagine not want do. anyhow, here's looks re-cast way:

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 run   ffoo.free;   inherited; end;  function tcontainer.getfoo: ifoo; begin   if not assigned(ffoo)     ffoo := tfooimpl.create(self);   result := ffoo; end;  procedure main; var   foo : ifoo; begin   foo := tcontainer.create;   foo.foo; end;  begin   main;   readln; end. 

the documentation talk this:

the class use implement delegated interface should derive taggregationobject.

initially not find documentation taggregationobject. , realised it's named taggregatedobject , documented.

taggregatedobject provides functionality inner object of aggregate implementing iinterface methods delegate controlling iinterface.

an aggregated object object composed of several interfaced objects. each object implements own behavior , interfaces, objects share same reference count, of controller object. in container pattern, controller container object.

taggregatedobject not support interfaces. however, typical of aggregate, implement methods of iinterface, used objects descend it. taggregatedobject, therefore, serves base classes implement interfaces creating objects part of aggregate.

taggregatedobject used base classes create contained objects , connecting objects. using taggregatedobject ensures calls iinterface methods delegate controlling iinterface of aggregate.

the controlling iinterface specified in constructor taggregatedobject , indicated controller property.

in addition there source code comments:

taggregatedobject , tcontainedobject suitable base classes interfaced objects intended aggregated or contained in outer controlling object. when using "implements" syntax on interface property in outer object class declaration, use these types implement inner object.

interfaces implemented aggregated objects on behalf of controller should not distinguishable other interfaces provided controller. aggregated objects must not maintain own reference count - must have same lifetime controller. achieve this, aggregated objects reflect reference count methods controller.

taggregatedobject reflects queryinterface calls controller. such aggregated object, 1 can obtain interface controller supports, , interfaces controller supports. useful implementing controller class uses 1 or more internal objects implement interfaces declared on controller class. aggregation promotes implementation sharing across object hierarchy.

taggregatedobject aggregate objects should inherit from, when used in conjunction "implements" syntax.


Popular posts from this blog

How to calculate SNR of signals in MATLAB? -

c# - Attempting to upload to FTP: System.Net.WebException: System error -

ios - UISlider customization: how to properly add shadow to custom knob image -