Any interface in Delphi inherits from IInterface (which is a nickname for IUnknown). It is nice for reference-counted interfaces, but sometimes we do not need reference counting at all. Consider the following example:
unit IValues; interface type IValue = interface(IInterface) function GetValue: Integer; end; function GetIValue: IValue; implementation type TValueObject = class(TObject, IValue) protected FValue: Integer; function GetValue: Integer; public constructor Create(AValue: Integer); end; var FValueObject: TValueObject; function GetIValue: IValue; begin Result:= FValueObject; end; constructor TValueObject.Create(AValue: Integer); begin FValue:= AValue; end; function TValueObject.GetValue: Integer; begin Result:= FValue; end; initialization FValueObject:= TValueObject.Create(11); finalization FValueObject.Free; end.
The above code does not compile because TValueObject does not implement IUnknown. A workaround is to implement stub methods for IUnknown:
type TValueObject = class(TObject, IValue) protected FValue: Integer; function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; function GetValue: Integer; public constructor Create(AValue: Integer); end; function TValueObject.QueryInterface(const IID: TGUID; out Obj): HResult; begin if GetInterface(IID, Obj) then Result:= S_OK else Result:= E_NOINTERFACE; end; function TValueObject._AddRef: Integer; begin Result:= -1; end; function TValueObject._Release: Integer; begin Result:= -1; end;
You can find the same code in VCL sources (TCustomVariantType class from Variants.pas unit).
Now, why should I implement IUnknown in my code if I don’t need it at all?
The above implementation of IUnknown looks like a standard implementation for non-reference-counted interfaces in Delphi. Why not to include it into System.pas and apply compiler magic to make the code in the first example compilable and legitimate? The implementation does not use additional object fields (TInterfacedObject implementation requires additional FRefCount field), so it seems like all that is required from the compiler is to insert pointers to the default IUnknown method’s implementations into the interface tables of any class that does not implement or inherit these methods can be implemented directly in TObject. It will save the programmer from writing a useless duplicate code. The compiler may also issue a warning for the safety reasons, if necessary.