I was 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:TSomecla开发者_开发问答ss;
implementation
...
initialization
someclass:=TSomeclass.Create;
finalization
someclass.Free;
rather than
type Tsomeclass=class
private class procedure proc1;
public
class var someint:integer;
class procedure proc2;
end;
90% of the classes in the project I'm working on have and need only one instance.Do I really have to use the first way for using those classes? Is it better optimized,handled by Delphi?
Sorry,I have no arguments to backup this hypothesis,but I want an expert's opinion.
Thanks in advance!
If you create a class that contains only class variables and class methods then you can use it without the instantiation. I.e. in your second example you could use Tsomeclass.proc2 (but not Tsomeclass.someint because this variable was not marked with the 'class' prefix as the Uwe pointed out).
For (unmesureably small) speed difference you can also mark your class methods as 'static'.
type
TSomeclass = class
class procedure proc2; static;
end;
There's no "handle better" comparison in my opinion here. Delphi allows you to put 'normal' and 'class' members in the class. Former you can use only on an instantiated object and latter you can use anywhere. But that's just two parts of the OO support in Delphi.
EDIT: To answer the question about the speed ...
Let's put together 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 enabled optimisation compiles .A/.B/.C calls into
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
The object is first created and its address is stored away into the ebx register.
To call tc.A, compiler prepares parameter (42 or $2A) in edx, the address of the 'tc' instance in the eax and calls TTestClass.A.
Almost the same happens in the tc.B case except that ebx is dereferenced.
In .A and .B case, eax contains the value of the 'Self' (equivalent to C++'s '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's pointing to the type info for the TTestClass but I'm not really sure about that).
When the code calls tc.C, only eax is prepared because 'static' methods can't reference the 'Self'.
Similar situation occurs in the TTestClass.B/.C cases except that 'Self' is loaded from some constant location when ??address of the TTestClass typeinfo?? is stored. Anyway, eax contains the same value when B is called via the instance (tc.B) or via the class (TTestClass.B).
So you can see that static calls require one 'mov' less. That was the inmesurable speedup I was refering to.
Are you saying one instance or no instances?
With your second example, you can't instantiate that.
I've yet to see anyone use Static classes in production code. You can still declare static (class) methods in your first example.
Use a regular typed class, but declare class var
, class procedure
, and class function()
. You can call the class methods and reference the class variables without creating an instance.
Like this:
type
TSomeClass = class(TObject)
class var
somevar: String;
class procedure Hello;
end;
Note that class variables were added somewhere after Delphi 7, but you should definitely be able to do class methods.
精彩评论