Class Variables.

Posted by on in Blogs
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;
Tags: Delphi


About
Gold User, Rank: 19, Points: 169
Product Marketing Manager & Associate Product Manager, InterBase. @DelphiABall

Comments

  • Guest
    Donovan Boddy Thursday, 18 October 2012

    Nice Post!

  • Guest
    Darian Thursday, 18 October 2012

    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;

  • Guest
    Oblong Manifesto Friday, 19 October 2012

    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.

  • Guest
    Stephen Ball Friday, 19 October 2012

    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

  • Please login first in order for you to submit comments
  • Page :
  • 1

Check out more tips and tricks in this development video: