In Delphi, avoid having a TComponent descendant implement interfaces, unless you are prepared to handle your refcounting
Posted by jpluimers on 2020/12/15
Every now and then I see code, where a class descending from TComponent
implements some interfaces, only interface references are used to the instances, and the expected behaviour is that the instances will free themselves when all the references went out of scope.
Bummer: TComponent
by default is not reference counted.
It is when you assign VCLComObject
an IVCLComObject
which is hell to implement (Delphi provides two of them: TVCLAutoObject
and TActiveFormControl
. They sound heavey, and are).
Do not go that way. If you need some form of ownership in a class implementing an interface, then descend the class from TInterfacedObject
, and add a field of TComponent
that is the owner of things that need to be freed later on. In the destructor, free that field.
Something like this:
unit InterfacedObjectWithRootUnit; interface type TInterfacedObjectWithRoot = class(TInterfacedObject) strict private FRoot: TComponent; function GetRoot: TComponent; strict protected property Root: TComponent read GetRoot; public destructor Destroy; override; end; implementation destructor TInterfacedObjectWithRoot.Destroy; begin if Assigned(FRoot) then begin FRoot.Free(); FRoot := nil; end; inherited Destroy(); end; function TInterfacedObjectWithRoot.GetRoot: TComponent; begin if FRoot = nil then FRoot := TComponent.Create(nil); Result := FRoot; end; end.
–jeroen
Leave a Reply