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.
<?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');
?>
[CONSOLE] Processing: Task A [CONSOLE] Complete [FILE:app.log] Processing: Task B [FILE:app.log] Complete TConsoleLogger supports ILogger