Properties

Properties are "virtual fields" that provide controlled access to object data. They can map directly to a field or use getter and setter methods to implement logic when a value is accessed or modified.

Basic Properties

A property is declared with a read and/or write specifier.

  • Field-backed: Directly reads from or writes to a private field.
  • Method-backed: Calls a getter function or a setter procedure.
type
  TUser = class
  private
    FName: String;
    FAge: Integer;
    procedure SetAge(Value: Integer);
    begin
      if Value < 0 then raise new Exception('Age cannot be negative');
      FAge := Value;
    end;
  public
    property Name: String read FName write FName;
    property Age: Integer read FAge write SetAge;
  end;

Access Control

You can create read-only or write-only properties by omitting one of the specifiers:

type
  TExample = class
  private
    FSecret: String;
  public
    property Secret: String read FSecret;
  end;

Auto-Implemented Properties

If you omit the read and write clauses, DWScript will automatically generate a backing field for the property. This reduces boilerplate code for simple data containers.

type
  TUser = class
    // Automatically creates a private field and getter/setter
    property Name: String;
    // You can mix auto-implemented properties with standard ones
    property Age: Integer;
    
    // Also works for class properties (static fields)
    class property Count: Integer; 
  end;

var u := new TUser;
u.Name := 'Bob';
TUser.Count := 1;

Array Properties

Array properties allow you to access data using an index, mimicking array syntax (obj[index]).

type
  TStringList = class
  private
    FItems: array of String;
    function GetItem(index: Integer): String;
    begin
       Result := FItems[index];
    end;
    procedure SetItem(index: Integer; value: String);
    begin
       FItems[index] := value;
    end;
  public
    property Items[index: Integer]: String read GetItem write SetItem;
  end;

Default Properties

If an array property is marked as default, you can omit the property name when accessing it.

type
  TMyContainer = class
  public
    function GetItem(index: Integer): String;
    begin
       Result := 'Item ' + IntToStr(index);
    end;
    property Items[index: Integer]: String read GetItem; default;
  end;

var list := TMyContainer.Create;
PrintLn(list[0]);
Result
Item 0

Indexed Properties

Indexed properties allow multiple properties to share the same getter or setter by passing a constant index value to the accessor.

type
  TSensor = class
  private
    function GetValue(index: Integer): Float;
    begin
       case index of
         0: Result := 22.5;
         1: Result := 45.0;
       else
         Result := 0.0;
       end;
    end;
  public
    property Temperature: Float index 0 read GetValue;
    property Humidity: Float index 1 read GetValue;
  end;

var s := TSensor.Create;
PrintLn(FloatToStr(s.Temperature));
Result
22.5

Class Properties

Class properties allow you to access a property directly through the class type without an instance. They must use class methods or class fields as their accessors.

type
  TSystem = class
    class function GetVersion: String;
    begin
       Result := '1.0.0';
    end;
    class property Version: String read GetVersion;
  end;

PrintLn(TSystem.Version);
Result
1.0.0

Expression-based Properties

DWScript allows you to define properties using expressions directly in the declaration, avoiding the need for boilerplate getter or setter functions. Expressions must be enclosed in parentheses.

type
  TCircle = class
    Radius : Float;
    // Read expression
    property Diameter : Float read (Radius * 2);
    // Read and write expressions
    property Area : Float 
      read (PI * Sqr(Radius))
      write (Radius := Sqrt(Value / PI));
  end;

var c := new TCircle;
c.Radius := 5;
PrintLn(c.Diameter.ToString);
c.Area := 100;
PrintLn(c.Radius.ToString);
Result
10
5.64189583547756

Property Promotion

Subclasses can redeclare a property from a parent class to change its visibility (e.g., from protected to public) or to provide a new implementation.

type
  TBase = class
  private
    FValue : Integer;
  protected
    property Value: Integer read FValue;
  end;
type
  TSub = class(TBase)
  public
    property Value;
  end;
On this page