Reputation: 399
I need a class implementing interface with no reference counting. I did the following:
IMyInterface = interface(IInterface)
['{B84904DF-9E8A-46E0-98E4-498BF03C2819}']
procedure InterfaceMethod;
end;
TMyClass = class(TObject, IMyInterface)
protected
function _AddRef: Integer;stdcall;
function _Release: Integer;stdcall;
function QueryInterface(const IID: TGUID; out Obj): HResult;stdcall;
public
procedure InterfaceMethod;
end;
procedure TMyClass.InterfaceMethod;
begin
ShowMessage('The Method');
end;
function TMyClass.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if GetInterface(IID, Obj) then
Result := 0
else
Result := E_NOINTERFACE;
end;
function TMyClass._AddRef: Integer;
begin
Result := -1;
end;
function TMyClass._Release: Integer;
begin
Result := -1;
end;
Lack of reference counting works fine. But my concern is that I cannot cast TMyClass
to IMyInterface
using as
operator:
var
MyI: IMyInterface;
begin
MyI := TMyClass.Create as IMyInterface;
I am given
[DCC Error] E2015 Operator not applicable to this operand type
The problem disappears when TMyClass
derives from TInterfacedObject
- i.e. I can do such casting without compiler error. Obviously I do not want to use TInterfacedObject as a base class as it would make my class reference counted. Why is such casting disallowed and how one would workaround it?
Upvotes: 9
Views: 5655
Reputation: 613312
The reason you cannot use as
in your code is that your class does not explicitly list IInterface
in its list of supported interfaces. Even though your interface derives from IInterface
, unless you actually list that interface, your class does not support it.
So, the trivial fix is to declare your class like this:
TMyClass = class(TObject, IInterface, IMyInterface)
The reason that your class needs to implement IInterface
is that is what the compiler is relying on in order to implement the as
cast.
The other point I would like to make is that you should, in general, avoid using interface inheritance. By and large it serves little purpose. One of the benefits of using interfaces is that you are free from the single inheritance constraint that comes with implementation inheritance.
But in any case, all Delphi interfaces automatically inherit from IInterface
so in your case there's no point specifying that. I would declare your interface like this:
IMyInterface = interface
['{B84904DF-9E8A-46E0-98E4-498BF03C2819}']
procedure InterfaceMethod;
end;
More broadly you should endeavour not to use inheritance with your interfaces. By taking that approach you will encourage less coupling and that leads to greater flexibility.
Upvotes: 15