- DelphiTools - https://www.delphitools.info -

Property expressions and statements

Object Pascal does allow binding a property to a field for direct read/writer, but we all have seen properties that required a slightly more complex getter or setter, and that usually meant a method for both. DWScript [1] (svn trunk) & Smart Pascal [2] (1.1) now support property expressions and statements, so the syntax is extended to allow:

property Name : Type read (expression) write (expression|statement)

Under the hood, the compiler will generate an unnamed getter or setter method when appropriate.

Let’s take f.i. a class that exposes an internal list, you can now use just

TMyClass = class
      FList : array of TElement;
      property Items[i: Integer] : TElement read (FList[i]) 
                                            write (FList[i]); default;
      property Count : Integer read (FList.Length);

Look Ma! No implementation and no constructor needed for trivial properties!
The astute reader will quickly notice how much shorter this is compared to doing it with a TList<T> and classic properties instead.

And for an hypothetical angle value types that accepts both radians and degrees you could have

TMyAngle = record
      FAngle : Float;
      property Radians : Float read FAngle write FAngle;
      property Degrees : Float read (RadToDeg(FAngle)) 
                               write (FAngle:=DegToRad(Value));

In the setter statement, there is a special value creatively named… “Value” which holds the value assigned to the property.

In addition to expressions and statements, you can also if specify a property name as getter or setter, this will create an alias (no under-the-hood getter or setter method will be created):

TAncestor = class
      FHidden : Integer;
      procedure SetSecret(v : Integer);
      property Hidden : Integer read FHidden write FHidden;
      property Secret : Integer write SetSecret;

TSubClass = class (TAncestor)
      property Revealed : Integer read Hidden write Secret;
      property OldReveal : Integer read Revealed write Revealed; deprecated;

Which can be of use when you want to make public a protected property under a different name in a subclass, and the underlying field or method being private wasn’t visible. It can also be helpful if you want to rename a property in a migration-friendly way, with the old name deprecated.

So to summarize:

As we weren’t sure of the potential ambiguity, the compiler currently requires the presence of brackets ( ) before the new expressions and statements are allowed, this requirement might be lifted in the future, or maybe not, as it makes such expressions stand out more.
This is an open question, Oxygen [3] accepts read expressions without brackets (but doesn’t have write expressions or statements), so feedback on this aspect is welcome.

Thanks go to Primoz Gabrielcic [4] for providing the unit tests for the above feature!