Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Introducing interfaces into an existing class hierarchy in Delphi

Are there any side effects to changing a class hierarchy's ancestor from TObject to TInterfacedObject so that I can implement interfaces further down the inheritance chain?

I've programmed in Delphi for several years but never encountered interfaces. I became accustomed to using them in other languages. Now that I'm involved in a Delphi project again I'd like to start taking advantage of them but I know they work a bit differently than in Java or C#.

like image 697
Kenneth Cochran Avatar asked Jan 21 '23 05:01

Kenneth Cochran


2 Answers

If you already have existing code using the class you will probably have to modify a lot of it to keep references to interfaces instead of object instances. Interfaces are reference counted and released automatically, as a result, any reference to the implementor instance will become an invalid pointer.

like image 92
Ondrej Kelle Avatar answered Jan 23 '23 18:01

Ondrej Kelle


This will work fine as long as you inherit from the class below at the top (bottom?) of your hierarchy. This code ensures that your new classes dont free themselves - as is the default behaviour of TInterfaceObject - you are presumably already freeing them yourself and want to preserve this. This activity is actually exactly what TComponent in the VCL does - it supports interfaces but is not reference counted.

type


  TYourAncestor = class( TInterfacedObject )
    function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;

  end;



implementation



function TYourAncestor.QueryInterface(const IID: TGUID; out Obj): HResult;
const
  E_NOINTERFACE = HResult($80004002);
begin
  if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE;
end;


function TYourAncestor._AddRef: Integer;
begin
  Result := -1   // -1 indicates no reference counting is taking place
end;

function TYourAncestor._Release: Integer;
begin
  Result := -1   // -1 indicates no reference counting is taking place
end;
like image 40
Brian Frost Avatar answered Jan 23 '23 17:01

Brian Frost