Does Delphi really do dynamic classes better than static ones?
I've been told more than once that Delphi handles dynamic classes better than static.Thereby using the following:
type Tsomeclass=class(TObject)
private procedure proc1;
public
someint:integer;
procedure proc2;
end;
var someclass:TSomeclass;
implementation
...
initialization
someclass:=TSomeclass.Create;
finalization
someclass.Free;
but not
type Tsomeclass=class
private class procedure proc1;
public
class var someint:integer;
class procedure proc2;
end;
90% of the classes in a project I am working on have and need only one instance. Do I really need to use the first way to use these classes? Is it optimized, handled by Delphi?
Sorry, I have no arguments to back up this hypothesis, but I want an expert opinion.
Thanks in advance!
source to share
If you create a class that only contains class variables and class methods, you can use it without instantiating it. That is, in your second example, you can use Tsomeclass.proc2 (but not Tsomeclass.someint, because this variable was not prefixed with "class" as Uwe pointed out).
For a (imperceptibly small) difference in speed, you can also mark class methods as "static".
type
TSomeclass = class
class procedure proc2; static;
end;
In my opinion, no comparison with the "pen is better". Delphi allows you to add "normal" and "cool" to a class. A former user can only use an instance of an object, while the latter can be used anywhere. But these are just two parts of the OO support in Delphi.
EDIT: To answer the question about speed ...
Add up a small test program:
program Project61;
{$APPTYPE CONSOLE}
type
TTestClass = class
procedure A(a: integer);
class procedure B(b: integer);
class procedure C(c: integer); static;
end;
procedure TTestClass.A(a: integer); begin end;
class procedure TTestClass.B(b: integer); begin end;
class procedure TTestClass.C(c: integer); begin end;
var
tc: TTestClass;
begin
tc := TTestClass.Create;
tc.A(42);
tc.B(42);
tc.C(42);
tc.Free;
//TTestClass.A(42); // not possible
TTestClass.B(42);
TTestClass.C(42);
end.
Delphi 2010 with compilation optimization enabled .A / .B / .C calls in
Project61.dpr.30: tc := TTestClass.Create;
004060C5 B201 mov dl,$01
004060C7 A154594000 mov eax,[$00405954]
004060CC E847DAFFFF call TObject.Create
004060D1 8BD8 mov ebx,eax
Project61.dpr.31: tc.A(42);
004060D3 BA2A000000 mov edx,$0000002a
004060D8 8BC3 mov eax,ebx
004060DA E899F9FFFF call TTestClass.A
Project61.dpr.32: tc.B(42);
004060DF BA2A000000 mov edx,$0000002a
004060E4 8B03 mov eax,[ebx]
004060E6 E891F9FFFF call TTestClass.B
Project61.dpr.33: tc.C(42);
004060EB B82A000000 mov eax,$0000002a
004060F0 E88BF9FFFF call TTestClass.C
Project61.dpr.34: tc.Free;
004060F5 8BC3 mov eax,ebx
004060F7 E84CDAFFFF call TObject.Free
Project61.dpr.36: TTestClass.B(42);
004060FC BA2A000000 mov edx,$0000002a
00406101 A154594000 mov eax,[$00405954]
00406106 E871F9FFFF call TTestClass.B
Project61.dpr.37: TTestClass.C(42);
0040610B B82A000000 mov eax,$0000002a
00406110 E86BF9FFFF call TTestClass.C
First, an object is created and its address is stored in the ebx register.
To call tc.A, the compiler prepares a parameter (42 or $ 2A) in edx, the address of the instance 'tc' in eax, and calls TTestClass.A.
Much the same happens for tc.B, except that ebx is dereferenced.
In the case of .A and .B, eax contains the value "Self" (equivalent to C ++ 'this'). When tc.A is called, eax contains the address of the "tc" instance. When tc.B is called, eax contains something else (I'm guessing it points to type information for TTestClass, but I'm not sure about that).
When the code calls tc.C, only eax is ready, because "static" methods cannot refer to "i".
A similar situation occurs in TTestClass.B / .C cases, except that "Self" is loaded from some persistent location when the TTestClass address is typeinfo ?? stored. Either way, eax contains the same value when B is called through an instance (tc.B) or through a class (TTestClass.B).
So you can see that the static calls require less mov. This was the pointless acceleration I was talking about.
source to share
Are you talking one instance or no instances?
In your second example, you cannot create this.
I have not yet seen anyone use static classes in production code. You can still declare static (class) methods in the first example.
Use a regular typed class, but declare class var
, class procedure
and class function()
. You can call class methods and specify class variables without instantiating.
Like this:
type
TSomeClass = class(TObject)
class var
somevar: String;
class procedure Hello;
end;
Note that class variables were added sometime after Delphi 7, but you will certainly be able to execute class methods.
source to share