Overview

Interfaces & Polymorphism

Showcases the power of interface-driven design for creating decoupled and extensible architectures. This example demonstrates defining interfaces, implementing multiple behaviors across disparate class hierarchies, and using the 'implements' operator for safe runtime discovery and casting of interface implementations.

Source Code

<?pas
type
  ILogger = interface
    procedure Log(msg: String);
  end;

type
  ISerializer = interface
    function Serialize(data: Variant): String;
  end;

// Console logger implementation
type
  TConsoleLogger = class(TObject, ILogger)
    procedure Log(msg: String);
    begin
      PrintLn('[CONSOLE] ' + msg);
    end;
  end;

// File logger implementation  
type
  TFileLogger = class(TObject, ILogger)
    FPrefix: String;

    constructor Create(prefix: String);
    begin
      FPrefix := prefix;
    end;

    procedure Log(msg: String);
    begin
      PrintLn('[FILE:' + FPrefix + '] ' + msg);
    end;
  end;

// Function accepting interface (polymorphism)
procedure ProcessWithLogging(logger: ILogger; data: String);
begin
  logger.Log('Processing: ' + data);
  logger.Log('Complete');
end;

// Using different implementations interchangeably
var console: ILogger := new TConsoleLogger;
var fileLog: ILogger := new TFileLogger('app.log');

ProcessWithLogging(console, 'Task A');
ProcessWithLogging(fileLog, 'Task B');

// Runtime check with 'implements' operator
if TConsoleLogger implements ILogger then
  PrintLn('TConsoleLogger supports ILogger');
?>

Result

[CONSOLE] Processing: Task A
[CONSOLE] Complete
[FILE:app.log] Processing: Task B
[FILE:app.log] Complete
TConsoleLogger supports ILogger
On this page