Interfaces

Interfaces define a contract that classes can implement. They allow for polymorphism without inheritance.

Defining an Interface

An interface is declared using the interface keyword. It can contain methods and properties, but no fields or implementation logic.

Interfaces can optionally be assigned a GUID (Globally Unique Identifier). In DWScript, the GUID is parsed but ignored by the compiler. It is primarily supported for source compatibility with Delphi.

type
  ISerializable = interface
    ['{7D8B1A20-1F2E-4B3C-A4D5-E6F708192A3B}']
    function Serialize: String;
  end;

Properties in Interfaces

Interfaces can include properties. These are implemented by the class that supports the interface.

type
  IShape = interface
    function GetArea: Float;
    // Standard property mapping to a getter
    property Area: Float read GetArea;
    
    // Expression-based property in interface!
    // The implementing class must satisfy the expression's requirements (e.g. have a GetArea function).
    property DoubleArea: Float read (GetArea * 2);
  end;

Implementing an Interface

A class implements an interface by listing it in its declaration and providing implementations for all its methods.

In DWScript, classes implicitly inherit from TObject if no base class is specified. While you can explicitly inherit from TObject for clarity (as in Delphi), it is not strictly required.

type
  ISerializable = interface
    function Serialize: String;
  end;

type
  TUser = class(ISerializable)
    FName: String;
    function Serialize: String;
    begin
       Result := '{"name": "' + FName + '"}';
    end;
  end;

var u := new TUser;
u.FName := 'Alice';

var s: ISerializable := u;
PrintLn(s.Serialize);
Result
{"name": "Alice"}

The implements Operator

DWScript provides the implements binary operator to check if an object instance or a class type supports a specific interface at runtime. This is similar to the is operator used for classes.

type
  IMyInterface = interface
    procedure DoWork;
  end;
type
  TWorker = class(IMyInterface)
    procedure DoWork; begin end;
  end;

var obj := new TWorker;

// Check instance
if obj implements IMyInterface then
  PrintLn('Object implements interface');

// Check class type
if TWorker implements IMyInterface then
  PrintLn('Class implements interface');
Result
Object implements interface
Class implements interface

DWScript uses ARC (Automatic Reference Counting) for all script objects, so interfaces do not require a separate lifetime management implementation like TInterfacedObject in Delphi.

On this page