Delphi Class variable per class - delphi

I've added a class variables to the base class of a deep class hierarchy. It's an integer intended to count number of instances created per class type. But I've run into a problem.
Given the example:
TBaseClass = class
private
class var fCreated: integer;
public
class function NewInstance: TObject; override;
end;
TDescendant = class(TBaseClass)
end;
...
class function TBaseClass.NewInstance: TObject;
begin
result := inherited NewInstance;
inc(fCreated);
end;
I assumed that I can use the class var to store the number of instances created per class, but this does not seem to be the case.
Inspecting TBaseClass.fCreated returns same value as TDescendant.fCreated, changing one via inspector changes the other, so it behaves as if fCreated is a single global var.
I expected fCreated to be maintained per class type, isn't that the point ? What am I missing ?

You are missing nothing. Your analysis of how class variables work is correct. A class var is nothing more than a global variable that is scoped by the class.
One simple solution for you is to use a dictionary to count the instances. A more hacky approach is to use a trick of mine that Hallvard Vassbotn blogged about, which (ab)uses the VMT to store class-specific fields. You can read all about it here.

You see TDescendant.fCreated as the same as TBaseClass.fCreated, becuse they are in the same unit, and therefore TDesendant sees the TBaseClass private fields. If you put them into separeted units, this will be over. Of if you declare fCreated not as Prvate, but Strict Private, TDescendant won't see it.

Related

Multiple generation of Obj with a generic class

I'm having some trouble with generics and constructors.
I would like to have a Generic class that can handle (and create) multiple objects of the same class. Moreover, I have some code that I would like to use whatever the specific class actually is.
I thought Generics are a good solution to this, but I'm not quite sure.
type
TMultiBlock<T: IBlock, constructor> = class(TObject)
blocks: array of array of T;
constructor Create(const owner: someClass, const n: integer);
end;
constructor TMultiBlock<T>.Create(const owner: someClass, const n: integer);
var
i: integer;
begin
for i := 0 to n-1 do
T.Create();
end;
The solution above works, but the Create() that is called is not the one of the class T that I give to the Generic.
I know that I can do the Create outside the TMultiBlock class, since I know class T there, as show below:
TM := TMultiBlock<TFinestra>.Create();
for i := 0 to n do
begin
TM.blocks[i] := TFinestra.Create();
end;
Here the class TFinestre is one of the class that I want to use in the Generic. But the thing is that I want to do some common operations on the T element, and these operation will be common to whatever the T type is, so I would like to do them on the TMultiBlock.
IBlock is an interface implemented by each class of type T.
An Interface is, in OOP terms, a pure abstract definition. It can be implemented by lots of different classes. You can't create objects from an interface (unless the interface gives you a method to create an object), you can get an interface from an Object if that object supports it. As all interfaces are implemented by a class then they can do different things, but ultimately what they do is dependent on what the object is, so you are back to having to know the class.
If you want to create the objects you have to know the class of the object you are creating. The interface could provide a method for returning the class of the object which is implementing the interface, allowing you to create more of them, but then you may as well use that class.
If your different types do not have a common ancestor, then you can specify, as you have, that T must support an interface, but you still instantiate the TMutliBLOCK<T> with a class. As interfaces are always implemented by a class then T will always derive from TObject so it will always support Create. The problem is you can't call T.Create unless IBlock includes the definition of Create ...
This means that you can have a TMulitBLOCK and a TMultiBLOCK but each would be holding the objects you have declared for it. If they're not inheriting from a common class then you would not be able to restrict the type of T to that common ancestor.
You can check that the type you are using supports an interface in the constructor, and then restrict to TObject.
TMultiBLOCK<T: class> = class(TObject)
protected
blocks: TArray<T>;
public
constructor Create(AOwner: pSomeObject; nSize: Integer);
end;
constructor TMultiBLOCK<T>.Create(AOwner: pSomeObject; nSize: Integer);
begin
if(not Supports(T, IBlock)) then
raise EInvalidCast.Create('Class '+T.ClassName+' must support IBlock')
else
...
end;
To call the members of IBlock you will need to get an interface pointer for each object. Bear in mind that depending on the implementation in the different implementing classes then when the interface references go out of scope the object may delete itself. To prevent that happening you probably want to store the interface references alongside the objects when you create them so the reference count is held above 0.
If you can organise the code so that all members are derived from a common ancestor then you can restrict your TMultiBLOCK<T> to that common ancestor, rather than a common interface.

Why make a class with only 1 static function?

Recently I ran into the following code:
interface
TSomeClass=Class
public
class function SomeFunction(sMyString: string) : ISomeInterface;
end;
implementation
TSomeClass.SomeFunction(sMyString: string) : ISomeInterface;
begin
...Get some dependency.
end;
Basically a class with 1 class function in it.
What's the benefit of this construct over just having the function in a unit without it being part of a class?
like:
interface
function SomeFunction(sMyString: string) : ISomeInterface;
implementation
SomeFunction(sMyString: string) : ISomeInterface;
begin
...Get some dependency.
end;
It largely comes down to personal choice.
However, one benefit that the class function provides is a means to fake namespaces. Suppose that the function name that you wanted to use was quite short and general. In that situation it might collide with another symbol having the same name, defined in a different unit. At which point you might be subject to the vagaries of unit use order, and may need to fully qualify the name. By using a class function, you force the user to qualify the function name with its class.
Another point to make here is that the two alternatives that you present have a potentially significant difference. The class function in your question has a Self pointer. Unlike for an instance method, this refers to the class rather than an instance. To make the two functions completely equivalent you would declare the class function to be static.
class function SomeFunction(sMyString: string): ISomeInterface; static;
Of course, one thing that can be done with a non-static class function, is that it can be used where an of object method type is required.

How can I access a hidden member from a derived class?

I have two classes, one derived from the other. These classes both introduce variables with the same name. The variable in the derived class hides that in the super class.
How can I refer to the super class's variable from a method of the derived class?
type
TClass1 = class
protected
FMyVar: Integer;
end;
TClass2 = class(TClass1)
protected
FMyVar: Integer;
public
procedure Foo;
end;
procedure TClass2.Foo;
begin
//here I want access to FMyVar from TClass1
end;
There's nothing special. Each subclass automatically has access to things from its parent class, except those members that were marked private in the parent.
Sublasses declared in the same unit as their parent have access to members marked private. Use strict private instead to really prevent subclasses from accessing their inherited members.
You can gain access with a cast:
procedure TClass2.Foo;
begin
DoSomething(TClass1(Self).FMyVar);
end;
As a side note, I suggest you reconsider your design. The path you are taking leads to confusion and bugs.

Class constructor not called when class registration is done in that class constructor

I am writing a simple dependency injection / inversion of control system based on a TDictionary holding abstract class references with their respective implementor classes.
My goals are:
Avoid direct instantiation by type (obviously).
Inclusion of a class' unit in the dpr should be enough to have it registered and be available for selection and instantiation through the di/ioc system.
Declare concrete implementing classes in implementation section only.
Use class constructors instead of initialization sections.
Btw, I am aware that using class constructors to take advantage of smart linking and wanting the inclusion of a unit to be enough to make a class available are defeating each other. I want to use class constructors instead of initialization sections for other reasons as well. And I would like to keep all class initialization/registration code together instead of having to split it between the class constructor and initialization section.
Problem
I want the registration of the class into the factory to be in the class constructor. Unfortunately, the compiler doesn't think the class is "touched" by just using its type in its own class constructor.
When I put the registration function in the initialization section, then the compiler does think the class is touched and calls the class constructor. But that defeats the object of my exercise of keeping all class initialization code in the class constructor.
Two questions
Should the compiler consider the use of the class in its own class constructor "touching the class" or is that too much to expect the compiler to do?
Does anybody have any clever ideas on how I can still achieve my goals without using the initialization section?
Example
The abstract classes used in the application:
TSite = class abstract (TObject)
function GetURL: string; virtual; abstract;
property URL: string read GetURL;
end;
TSites = class (TList<TSite>);
TThisApplication = class abstract (TObject)
function Sites: TSites; virtual; abstract;
end;
The concrete implementing class (declared in the implementation section!) for TThisApplication
TThisApplicationConcrete = class(TThisApplication)
class constructor ClassCreate;
strict private
FSites: TSites;
function Sites: TSites; override;
end;
class constructor TThisApplicationConcrete.ClassCreate;
begin
RegisterImplementorClass(TThisApplication, TThisApplicationConcrete);
end;
function TThisApplicationConcrete.Sites: TSites;
var
SiteList: TSites;
begin
if not Assigned(FSites) then begin
SiteList := TSites.Create; // Change to use factory
//RetrieveSites(SiteList);
FSites := SiteList;
end;
Result := FSites;
end;
The function to get an instance of TThisApplication:
function ThisApplication: TThisApplication;
var
ImplementorClass: TClass;
begin
ImplementorClass := GetImplementorClass(TThisApplication);
if Assigned(ImplementorClass) then begin
Result := ImplementorClass.Create as TThisApplication;
end else begin
Result := nil;
end;
end;
This is currently coded in a separate function, but it w/could be moved to the factory.
Full example code
If anybody would like to experiment, I have the full code of my test projects available at : http://www.bjsoftware.com/delphistuff/stackoverdlow/classconstructors.zip
Zip contents:
4 projects all using the same source files, differing only in conditional defines (that's why the dproj's are also included)
4 source files
groupproj and its dsk with all 4 projects
RunTestApps.cmd to run all 4 projects
Results.txt with the output of my run of the RunTestApps.cmd
WriteUp.txt with the text of this question
Please bear in mind that at all times you need to do a "Build All Projecs" because all dcu's and exe's are going to the source dir and otherwise you are going to face a lot of errors and/or confusion because the exe isn't doing what its name indicates.
This is as expected. As Uwe pointed out, a self-referential class constructor isn't enough to trigger inclusion. Placing the reference in the initialization section will do the trick since that is outside the class itself. Trying to self-reference a class for inclusion is akin to trying pull yourself out of a deep hole by pulling on your own suspenders.
As long as you don't use the class anywhere outside the class itself, the compiler takes this as the class not used at all and hence won't call the class constructor. So I guess you have to use the intialization section instead of tweaking the code to fool the compiler. Take the pragmatic approach instead of the dogmatic one. It will be more readable anyway.
I think you expect the class constructor to work differently than it has been designed to. Class constructor don't get called "just before" the first create. (Not in WIN32 delphi at least). If a class is referenced, its class constructor will run before the unit's initialization code.
If the only reference that you have to your class happens to be inside said class, then no code actually linked into your application refer to said class. Therefore, its class constructor will never get called.
I believe register functions belongs to the initialization section. Having the register function there will force the class constructor to also be executed. I don't see why you would want/require the register code to be placed into the class constructor.
If you want more information about the way class constructor/destructor works, you can read this pretty good article by Allen Bauer:
http://blogs.embarcadero.com/abauer/2009/09/04/38899

Static classes in Delphi (Win32)

Is it in Delphi (Win32) possible to declare a whole class (not only a function of the class) as static?
Looks like user search for "class functions":
type
TSomeClass = class
class procedure MyFunction(...);
This is like static method, so, call it:
TSomeClass.MyFunction(...);
I assume you mean static classes like in .net (and not "static" as in traditional Delphi/Native) - and the answer to that is no.
I would use an abstract class (not to be confused with an abstract method in a class) to prevent it from being instantiated instead of demoting the constructor to protected:
TMyClass = class abstract
public
class procedure DoStuff; static;
end;
That will enforce the singleton pattern and prevent any instantiations period.
I am not quite sure what you mean by a "static class". You can declare a class, that has only class methods, so these methods can be called without instantiating the class.
TSomeClass.SomeMethod;
Is that what you want?
Not natively.
Depending on what you need it for, if for the purposes of your code, in some use cases you could replace it with a Singleton Pattern object.
For walkthrough on implementing this I'd recommend this guide which, covers almost any version of delphi, but if you're using Delphi 2010 you could also use the new class Constructors/Destructors for improved results.
You could create a class that contains nothing but static methods. If you have to maintain some sort of state, then the state variables should be passed as var parameters. There is no way to "properly" access static variables other than having a set of global variables in the implementation section of the class OUTSIDE the scope of the class, for example:
UNIT TestUnit;
INTERFACE
Type
TStaticClass = Class
public
procedure Foo(var Bar:String); static;
end;
IMPLEMENTATION
var
LastBar : String; // the last bar
LastRes : string; // the last result
Procedure TStaticClass.Foo(var Bar:String);
begin
if Bar <> LastBar then
LastRes := SomeCPUExpensiveProcess(Bar);
LastBar := Bar;
Bar := LastRes;
end;
INITIALIZATION
LastBar := '';
LastRes := SomeCPUExpensiveProcess('');
END.
You can also create a new unit called uDG_Utils for example, define a class, define a global variable for that class and in the initialization and finalization section you manage the class constructor and destructor.
Now all you need to do is call it like mySuperDuperClass.SuperMethod...
EDIT
I have edited this post to remove it. The answer is admittedly bad and deserves the down-votes. I don't want it to remain here to confuse or mislead anyone further.

Resources