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 comment