Simulating class properties in (Win32) Delphi

In Simulating class properties in (Win32) Delphi, there's this trick for defining 'class properties' as well as class methods:

unit myObjectUnit;

interface

type
  TMyObject = Class
  private
    class function GetClassInt: integer;
    class procedure SetClassInt(const Value: integer);
  public
    property ClassInt : integer read GetClassInt 
                                write SetClassInt;
  end;

implementation

{$WRITEABLECONST ON}
const TMyObject_ClassInt : integer = 0;
{$WRITEABLECONST OFF}

class function TMyObject.GetClassInt: integer;
begin
  result := TMyObject_ClassInt;
end;

class procedure TMyObject.SetClassInt(
  const Value: integer);
begin
  TMyObject_ClassInt := value;
end;

end.

I will only have one such object in my code, so the warning that the GetClassInt and SetClassInt are always operating on the same typed constant *TMyObject_ClassInt* does not apply:

procedure TForm1.Button1Click(Sender: TObject);
var
  myObject : TMyObject;
begin
  myObject.ClassInt := 2005;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  myObject : TMyObject;
begin
  ShowMessage(IntToStr(myObject.ClassInt));
end;

(This illustrates that warning: Click 1 then 2 and the message shows 2005, not 0).

Still, this code smells a bit fishy. Can I expect problems (other than the warning above)? Is there a better way?.

BTW I'm not talking about the brute force $WRITEABLECONST OFF - instead of returning to the previous state. That can be circumvented by:

{$IFOPT J-}
{$DEFINE WC_WAS_OFF}
{$ENDIF}
{$WRITEABLECONST ON}
const TMyObject_ClassInt : integer = 0;
{$IFDEF WC_WAS_OFF}
{$WRITEABLECONST OFF}
{$ENDIF}

Answers


There's a few things that need to be specified here:

First of all, since you've tagged this as XE2, it supports Class Properties properly, with Class Field Variables. This has been the case since (I think) Delphi 2009.

type
  TMyClass = class
    strict private
      class var         // Note fields must be declared as class fields
        FRed: Integer;
        FGreen: Integer;
        FBlue: Integer;
      public             // ends the class var block
        class property Red: Integer read FRed write FRed;
        class property Green: Integer read FGreen write FGreen;
        class property Blue: Integer read FBlue write FBlue;
  end;

Which can be accesed as:

TMyClass.Red := 0;
TMyClass.Blue := 0;
TMyClass.Green := 0;

For older versions of Delphi, this workaround is valid, though I'd use a unit variable instead of a writable constant as Uli suggested. In all cases, your primary problem is multithreaded access.


Need Your Help

Compare Version Identifiers

c# .net compare versions

Here is my code, which takes two version identifiers in the form "1, 5, 0, 4" or "1.5.0.4" and determines which is the newer version.

android two line listview row alignment

android listview android-linearlayout relativelayout

I've a two line listview with the following XML for the row:

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.