Every now and then I am doing something that I think would be benefited by virtual class vars. FPC already has class vars but every subclass accesses the same var. They are not virtual. In a way there are some hard coded virtual class vars such as TObject.ClassName
This shows how current class vars operate:
The output is
4321.With a virtual class var the output would be
1234. Unfortunately FPC does not have virtual class vars so I have devised a terrible hack.
In short I declare a virtual procedure that will never be used, this is a placeholder. Then create a class constructor which finds the index of that procedure in the VMT which is saved to a regular class var. Then I set the VMT entry to nil as if it's an unset variable. And the first part is done. For every virtual class var you will need a regular class var to hold the index of the placeholder VMT entry.
Now we need a way to set and unset our variable. We will have to access it using a virtual class function and procedure.In my case I used a string type.
Class properties cannot use virtual methods so I used a property that can only be accessed by an instance.
Here's the complete source for my example.
You may have noticed that I had to create a class constructor for TB. This is because the VMT for TB is already initialized with the address of TA.MyVarHolder.
To get around this I made the following changes.
The output is:
A Name = Hello
B Name = World
C Name = Hello
I added a base object TVirtualClassVarObject; It has a small framework to ease adding virtual class vars to descendant classes. It takes care of initializing class vars to nil in child classes in InitializeVirtualClassVars. You could also set a default value to something else. Each child class would get that default value.
For each variable you want to add you must declare an index variable, virtual procedure and the getter and setter methods. Then in InitializeVirtualClassVars call SetClassVarIndex with the index variable to set and the address of the virtual procedure.
Limitations. There are a couple of limitations I see. Variable types are limited in size to SizeOf(Pointer). If you need a more complex type stored you will have to store a pointer to the data and access it that way, like I have done with the string property. I haven't taken care of disposing of variables that are allocated. This wouldn't be too hard to add. However if you limit your variable types to basic types or pointers to existing data it shouldn't matter. When the class is destructing the program is about to end and it's memory will be freed anyway.
That's it. Now if you really want to you can add virtual class vars to your objects.