Interfaces in Delphi.Net

While porting the data aware controls in the Essentials component suite I discovered that the CM_GETDATALINK message is no longer used to get the component’s TDataLink reference. VCL.Net now uses the IDataLink interface to do the same thing. Essential’s data aware controls were easily fixed by making them implement the IDataLink interface and removing all references the the CM_GETDATALINK message.

Since I had never come across interfaces used this way in Delphi, I decided to do some reading on the topic. I found the CodeGear documentation on the topic to be a bit sparse for some one, like me, who didn’t already know what they were talking about. Here is my attempt to explain it in somewhat simpler terms.

To begin with an interface is declared in a way that is similar to a class declaration.

IMyInterface = interface
end;

An interface can only contain methods and properties. No fields are permitted and no access modifiers (private, protected, public, etc) are permitted. So, a more complete interface definition might look like this:

IMyInterface = interface
procedure MyMethod;
function GetMyProperty: Integer;
procedure SetMyProperty(Value: Integer);
property MyProperty: Integer read GetMyProperty write SetMyProperty;
end;

An interface cannot be instantiated like a class. It can only be implemented as part of a class. This is done using the multiple inheritance features of Delphi. Like this:

TMyClass = class(TObject, IMyInterface)
end;

An interface has no existence outside of the class that implements it. This means that the methods defined as part of the interface must be implemented as part of the class. Like this:

TMyClass = class(TObject, IMyInterface)
procedure MyMethod;
function GetMyProperty: Integer;
procedure SetMyProperty(Value: Integer);
end;

procedure TMyClass.MyMethod;
begin

end;

function TMyClass.GetMyProperty: Integer;

So much for the semantics. What are interfaces useful for?

An interface allows you to access the methods defined by the interface without needing to know what type of object contains the interface. Since the interface methods have full access to all members of the class that implements it, this means that you can use interface methods to get and set class fields and to execute class methods without knowing anything about the class itself. As long as you know the details of the interface you can access its methods and properties. Perhaps this easiest way to explain is by way of an example.

Let’s consider the CM_GETDATALINK message that started this whole thing. In Delphi for Win32 this message is used to get the TDataLink reference from a data aware control. Using this approach it was possible to find out if a control was data aware or not. You just sent a CM_GETDATALINK message to the control. If it replied with a non-nil value it was data aware and the return value was a pointer to its TDataLink. You didn’t need to know what type of control it was to be able to call one of its methods to find out.

Since pointers are a no-no in .Net this approach is no longer useful. So what you do now is define an interface and have all data aware controls implement that interface. When you need to find out if a control is data aware you use the is operator to find out if the control implements the interface and then use the as operator to cast the object reference to an interface reference and use that to execute the method to get the TDataLink reference. Like this:

IDataLink = interface
function GetDataLink: TDataLink;
end;

TDataAware = class(TControl, IDataLink)
private
FDataLink: TDataLink;
protected
function GetDataLink: TDataLink;
end;

function TDataAware.GetDataLink: TDataLink;
begin
Result := FDataLink;
end;

if (someControl is IDataLink) then
someDataLink := (someControl as IDataLink).GetDataLink;

One Response to “Interfaces in Delphi.Net”

  1. alex Says:

    Great post and great blog!
    Keep writing!
    Regards from Poland,
    Alex

Leave a Reply