Reputation: 3127
I have a doubt that I cannot solve. I have read the documentation at embarcadero for class constructors but I cannot understand the meaning of that. In other words, what is the usage difference between a constructor
and a class constructor
? I did this:
type
TGeneric<T> = class
private
FValue: T;
aboutString: string;
procedure setValue(const a: T);
public
property V: T read FValue write setValue;
property about: string read aboutString;
constructor Create;
destructor Destroy; override;
end;
implementation
{ TGeneric<T> }
constructor TGeneric<T>.Create;
begin
inherited;
aboutString := 'test';
end;
Instead this code is not working properly:
type
TGeneric<T> = class
private
FValue: T;
aboutString: string;
procedure setValue(const a: T);
public
property V: T read FValue write setValue;
property about: string read aboutString;
class constructor Create;
destructor Destroy; override;
end;
implementation
{ TGeneric<T> }
class constructor TGeneric<T>.Create;
begin
inherited;
aboutString := 'test';
end;
I guess that the answer is in this line of the documentation:
Normally, class constructors are used to initialize the static fields of the class or to perform a type of initialization, which is required before the class or any class instance can function properly.
Tell me if I am correct:
inherited Create;
, initialize variables and so on.For example look at below:
type
TBox = class
private
class var FList: TList<Integer>;
class constructor Create;
end;
implementation
class constructor TBox.Create;
begin
{ Initialize the static FList member }
FList := TList<Integer>.Create();
end;
end.
Here I am going to create the object immediately when I call TBox.Create
in the main form?
Upvotes: 17
Views: 24803
Reputation: 185
Quoting from Delphi 12 Athens documentation on this. It's not changed for years, having checked as far back as Berlin.
Class Constructors
A class constructor is a special class method that is not accessible to developers. Calls to class constructors are inserted automatically by the compiler into the
initialization
section of the unit where the class is defined. Normally, class constructors are used to initialize the static fields of the class or to perform a type of initialization, which is required before the class or any class instance can function properly. Even though the same result can be obtained by placing class initialization code into theinitialization
section, class constructors have the benefit of helping the compiler decide which classes should be included into the final binary file and which should be removed from it.The next example shows the usual way of initializing class fields:
type TBox = class private class var FList: TList<Integer>; end; implementation initialization { Initialize the static FList member } TBox.FList := TList<Integer>.Create(); end.
This method has a big disadvantage: even though an application can include the unit in which
TBox
is declared, it may never actually use theTBox
class. In the current example, theTBox
class is included into the resulting binary, because it is referenced in theinitialization
section. To alleviate this problem, consider using class constructors:type TBox = class private class var FList: TList<Integer>; class constructor Create; end; implementation class constructor TBox.Create; begin { Initialize the static FList member } FList := TList<Integer>.Create(); end; end.
In this case, the compiler checks whether
TBox
is actually used anywhere in the application, and if it is used, a call to the class constructor is added automatically to theinitialization
section of the unit.Note: Even though the compiler takes care of ordering the initialization of classes, in some complex scenarios, ordering may become random. This happens when the class constructor of a class depends on the state of another class that, in turn, depends on the first class.
Note: The class constructor for a generic class or record may execute multiple times. The exact number of times the class constructor is executed in this case depends on the number of specialized versions of the generic type. For example, the class constructor for a specialized
TList<String>
class may execute multiple times in the same application.Class Destructors
Class destructors are the opposite of class constructors in that they perform the finalization of the class. Class destructors come with the same advantages as class constructors, except for finalization purposes.
The following example builds on the example shown in class constructors and introduces the
finalization
routine:type TBox = class private class var FList: TList<Integer>; class constructor Create; class destructor Destroy; end; implementation class constructor TBox.Create; begin { Initialize the static FList member } FList := TList<Integer>.Create(); end; class destructor TBox.Destroy; begin { Finalize the static FList member } FList.Free; end; end.
Note: The class destructor for a generic class or record may execute multiple times. The exact number of times the class destructor is executed in this case depends on the number of specialized versions of the generic type. For example, the class destructor for a specialized
TList<String>
class may execute multiple times in the same application.
Upvotes: 2
Reputation: 11
In addition to my pre-posters, it should be mentioned that in your example, the class constructor of a generic class is being called each time you instantiate (reference) a genric specialization:
TGenClass<T: class> = class
public
class constructor Create;
class destructor Destroy;
end;
class constructor TGenClass<T>.Create;
begin
Writeln('TGenClass<', GetTypeName(TypeInfo(T)), '> created');
end;
class constructor TGenClass<T>.Create;
begin
Writeln('TGenClass<', GetTypeName(TypeInfo(T)), '> destroyed');
end;
initialization
RegisterClass(TGenClass<String>);
RegisterClass(TGenClass<Integer>);
The output will be:
TGenClass<String> created
TGenClass<Integer> created
TGenClass<String> destroyed
TGenClass<Integer> destroyed
Note however, that the class construction/destruction order does not necessarily have to match the declaration or reference order at all!
Upvotes: 1
Reputation: 612854
Self
is not defined.In the wild, class constructors are rare, constructors are as common as muck. Quite likely you have no immediate need for class constructors so feel free to ignore them for now. Concentrate on understanding how to write and use constructors.
If in the future you ever need to initialize variables owned by the class (as opposed to owned by an instance) then you might find yourself wanting to use a class constructor. Until that point in time, do feel free to ignore them.
Upvotes: 30