Watch, Follow, &
Connect with Us

Stephen Ball

Class Variables.

I got asked today about having a global value that you can share between objects of specific types but was closed away to other objects, so they didn’t want to have a global variable.

Two nice language feature in Delphi allows you to do exactly what they were trying to do, and they are Class Variables and strict private declarations. In this quick blog post we will look at this in action.

A Class Variable simply means you have a value that is managed by the class type rather than an instance of a class. This means that each time you reference it from ANY object of that type, you get the same value back. Strict Private means that only this class can read and write the value, even if there are other classes in the same unit of code.

To demonstrate this in action I’m going to write some bonkers code, totally impractical, but feel free to copy it :-) It does however prove the point and give an understanding of it in action. I will then suggest some more practical examples of this in action.

So lets start with our demo class TFoo You can see this class has an ID (string) and this is read and set to the private value FID. We also have a strict private member FrIDCounter (Read Counter) that is increased everytime the property ID is read. This value is declared as a class var meaning it belongs to the class type and not the instance. (highlighted in blue below)

unit unitFoo;
interface
uses
  System.SysUtils;

type
  TFoo = class
  strict private
    class var FrIDCounter : Integer;
  private
    FID: string;
    function GetID: string;
    procedure SetID(const Value: string);
  public
    constructor Create;
    procedure SetIDCounter(NewValue : Integer);
    property ID : string read GetID write SetID;
  end;

implementation

constructor TFoo.Create();
begin
  inherited Create;
  ID := '';
end;

function TFoo.GetID: string;
begin
  Result := FID +':'+ IntToStr(FrIDCounter);
  Inc(FrIDCounter);
end;

procedure TFoo.SetID(const Value: string);
begin
  FID := Value;
end;

procedure TFoo.SetIDCounter(NewValue: Integer);
begin
  TFoo.FrIDCounter := NewValue;
end;

end.

OK, I did say it would be bonkers code! But lets see how this works in action. To try this code out, I’m going to create two instances of the object TFoo, to show that the updates really do happen across both objects. To show the output I’ve put a ListBox onto a form, added a button and run the application, The code in the image below will show what happens.

From the above we can see that Foo1 is created with an ID of MyFoo1ID and this is kept by the object as the ID, however the ID is appended with the counter for each read. When Foo 2 is created, its counter is the next value along form Foo1 and then when Foo1 is called again, it takes the next number again!

The code, then sets the ID to 1000 and the next two reads carry on from the same value.

OK. Totally bonkers code, but a very useful language feature. Imagine that you need to keep a lot of objects aware of a remote connection protocol, or you need to update the currency conversion value across your system. This gives one way to do it simply.

However following on from our theme, imagine you want to create a number of objects with a unique ID for each object the following code would do just that thanks to the Class Variable.

type
  TFoo = class
  strict private
    class var FrIDCounter : Integer;
  private
    FID: string;
  public
    constructor Create;
    property ID : string read FID;
  end;
implementation
constructor TFoo.Create();
begin
  inherited Create;
  FID := FrIDCounter;
  Inc(FrIDCounter);
end;
Posted by Stephen Ball on October 18th, 2012 under Delphi |



5 Responses to “Class Variables.”

  1. Donovan Boddy Says:

    Nice Post!

  2. Darian Says:

    Thanks for the article. To be honest I haven’t used Class Variables much, but I would state that guarded access is required to class variables in multi-threaded programs… TMonitor.Enter(classvar);
    try;
    DoSomething(classvar);
    finally;
    TMonitor.Exit(classvar);
    end;

  3. Oblong Manifesto Says:

    I had never considered class variables in this way before - this is actually really useful and I can see that I could simplify some of my existing systems using this approach. The "remote connection protocol" variable particularly stood out to me.

  4. Stephen Ball Says:

    Great comments, thanks guys. Absolutely Darian, you would want to make this thread safe if using it in a multi-threaded application. There is more on TMonitor on docwiki.embarcadero.com

  5. ObjectMethodology.com Says:

    Bonkers code?

Leave a Comment



Server Response from: BLOGS2