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.