Interfaces in Delphi Programming 101

What's an Interface? Defining an Interface. Implementing an Interface.

mla apa chicago
Your Citation
Gajic, Zarko. "Interfaces in Delphi Programming 101." ThoughtCo, Jun. 22, 2017, Gajic, Zarko. (2017, June 22). Interfaces in Delphi Programming 101. Retrieved from Gajic, Zarko. "Interfaces in Delphi Programming 101." ThoughtCo. (accessed October 23, 2017).

In Delphi, keyword "interface" has two distinct meanings.

In OOP jargon, you can think of an interface as a class with no implementation.

In Delphi unit definition interface section is used to declare any public sections of code that appear in a unit.

This article will explain interfaces from an OOP perspective.

If you are up to creating a rock solid application in a way that your code is maintainable, reusable, and flexible the OOP nature of Delphi will help you drive the first 70% of your route.

Defining interfaces and implementing them will help with the remaining 30%.

Interfaces as Abstract Classes

You can think of an interface as an abstract class with all the implementation stripped out and everything that is not public removed.

An abstract class in Delphi is a class that cannot be instantiated - you cannot create an object from a class marked as abstract.

Let's take a look at an example interface declaration:

  IConfigChanged = interface['{0D57624C-CDDE-458B-A36C-436AE465B477}']
    procedure ApplyConfigChange;

The IConfigChanged is an interface. An interface is defined much like a class, the keyword "interface" is used instead of "class".

The Guid value that follows the interface keyword is used by the compiler to uniquely identify the interface. To generate a new GUID value, just press Ctrl+Shift+G in the Delphi IDE. Each interface you define needs a unique Guid value.

An interface in OOP defines an abstraction - a template for an actual class that will implement the interface - that will implement the methods defined by the interface.

An interface does not actually do anything - it only has a signature for interaction with other (implementing) classes or interfaces.

The implementation of the methods (functions, procedures and property Get/Set methods) is done in the class that implements the interface.

In the interface definition there are no scope sections (private, public, published, etc.) everything is public. An interface type can define functions, procedures (that will eventually become methods of the class that implements the interface) and properties. When an interface defines a property it must define the get/set methods - interfaces cannot define variables.

As with classes, an interface can inherit from other interfaces.

 IConfigChangedMore = interface(IConfigChanged)
   procedure ApplyMoreChanges;

Interfaces are NOT COM ONLY related

Most Delphi developers when they think of interfaces they think of COM programming. However, interfaces are just an OOP feature of the language - they are not tied to COM specifically.

Interfaces can be defined and implemented in a Delphi application without touching COM at all.

Implementing an Interface

To implement an interface you need to add the name of the interface to the class statement, as in:

  TMainForm = class(TForm, IConfigChanged)
    procedure ApplyConfigChange;

In the above code a Delphi form named "MainForm" implements the IConfigChanged interface.

Warning: when a class implements an interface it must implement all its methods and properties. If you fail/forget to implement a method (for example: ApplyConfigChange) a compile time error "E2003 Undeclared identifier: 'ApplyConfigChange'" will occur.

Warning: if you try to specify the interface without the GUID value you will receive: "E2086 Type 'IConfigChanged' is not yet completely defined".

When to use an interface? A Real World example. Finally :)

I have an (MDI) application where several forms can be displayed to the user at one time. When the user changes the application configuration - most forms need to update their display: show/hide some buttons, update label captions, etc.

I needed a simple way to notify all open forms that a change in the application configuration has happened.

The ideal tool for the job was an interface.

Every form that needs to be updated when the configuration changes will implement IConfigChanged.

Since the configuration screen in displayed modally, when it closes the next code ensures all IConfigChanged implementing forms are notified and ApplyConfigChange is called:

procedure DoConfigChange() ;
  cnt : integer;
  icc : IConfigChanged;
  for cnt := 0 to -1 + Screen.FormCount do
    if Supports(Screen.Forms[cnt], IConfigChanged, icc) then

The Supports function (defined in Sysutils.pas) indicates whether a given object or interface supports a specified interface.

The code iterates through the Screen.Forms collection (of the TScreen object) - all the forms currently displayed in the application.
If a form Screen.Forms[cnt] supports the interface, Supports returns the interface for the last parameter parameter and returns true.

Therefore if the form implements the IConfigChanged, the icc variable can be used to call the methods of the interface as implemented by the form.

Note, of course, that every form can have its own different implementation of the ApplyConfigChange procedure.

IUnknown, IInterface, TInterfacedObject, QueryInterface, _AddRef, _Release

I'll try to make the hard things simple here :)

Any class you define in Delphi needs to have an ancestor. TObject is the ultimate ancestor of all objects and components.

The above idea applies to interfaces also, the IInterface is the base class for all interfaces. IInterface defines 3 methods: QueryInterface, _AddRef and _Release.

This means that our IConfigChanged also has those 3 methods - but we have not implemented those. Here's why:

TForm inherits from TComponent that already implements the IInterface for you!

When you want to implement an interface in a class that inherits from TObject - make sure your class inherits from TInterfacedObject instead. Since TInterfacedObject is a TObject implementing IInterface. For example:

TMyClass = class(TInterfacedObject, IConfigChanged)
  procedure ApplyConfigChange;

To finalize this mess: IUnknown = IInterface. IUnknown is for COM.