Skip to content
Interfaces
step 1/5

Reading — step 1 of 5

Learn

~2 min readInterfaces, Operators, Idiomatic FPC

Object Pascal interfaces are like Java/C# interfaces — abstract contracts that classes implement.

Defining

type
    IDrawable = interface
        ['{B26E5476-1F73-4421-A8E1-9C42AB1C3D71}']
        procedure Draw;
        function Area: real;
    end;

The GUID (['{...}']) uniquely identifies the interface — use Ctrl+Shift+G in Lazarus IDE to generate one. Required for COM/OLE compatibility; for plain in-process use it's optional but conventional.

Implementing

type
    TCircle = class(TInterfacedObject, IDrawable)
    private
        FRadius: real;
    public
        constructor Create(R: real);
        procedure Draw;
        function Area: real;
    end;

TInterfacedObject provides reference-counted memory management — much cleaner than manual Free. As long as you assign through interface variables, refcount handles cleanup.

Using

var d: IDrawable;
begin
    d := TCircle.Create(5);
    d.Draw;
    WriteLn('area: ', d.Area);
    { No explicit Free — refcount drops to 0 when d goes out of scope }
end.

When the interface variable goes out of scope, refcount drops, the object is freed.

Multiple interfaces

A class can implement many:

TLogger = class(TInterfacedObject, ILogger, IDisposable)
    ...
end;

Interface inheritance

IBase = interface
    procedure A;
end;

IDerived = interface(IBase)
    procedure B;
end;

Classes implementing IDerived must implement A AND B.

Querying interfaces

var obj: TObject;
    drawable: IDrawable;
begin
    obj := TCircle.Create(5);
    if Supports(obj, IDrawable, drawable) then
        drawable.Draw
    else
        WriteLn('object does not draw');
end.

Supports is in SysUtils — checks and casts in one call. Returns false if not implemented.

Why interfaces matter

  • Decouple modules: callers depend on ILogger, not on a specific class
  • Enable mocking for tests
  • Support multiple inheritance of behavior (Pascal classes can only single-inherit, but can implement many interfaces)
  • Reference counting — easier memory management than raw classes

Caveats

  • Mixing interface variables and class variables to the same object can confuse refcount — pick one
  • Don't subclass TInterfacedObject in long chains — refcount setup is delicate
  • Performance: interface dispatch is slightly slower than direct class call (vtable indirection)

For large Pascal codebases, interfaces are how you keep modules from growing tightly coupled. Lazarus, FPC's RTL, and most CPAN-equivalent libraries are built around them.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…