我不止一次被告知Delphi比static更好地处理动态类。使用以下内容:
type Tsomeclass=class(TObject)
private procedure proc1;
public
someint:integer;
procedure proc2;
end;
var someclass:TSomeclass;
implementation
...
initialization
someclass:=TSomeclass.Create;
finalization
someclass.Free;
而不是
type Tsomeclass=class
private class procedure proc1;
public
class var someint:integer;
class procedure proc2;
end;
我正在处理的项目中有90%的类只需要一个实例。我真的必须使用第一种方法来使用这些类吗?是否更好地优化,由Delphi处理?
对不起,我没有理由支持这个假设,但我想要专家的意见。
提前致谢!
答案 0 :(得分:11)
如果创建一个只包含类变量和类方法的类,则可以在不实例化的情况下使用它。即在你的第二个例子中你可以使用Tsomeclass.proc2(但不是Tsomeclass.someint,因为这个变量没有像Uwe指出的那样用'class'前缀标记。)
对于(不可避免的小)速度差异,您还可以将您的类方法标记为“静态”。
type
TSomeclass = class
class procedure proc2; static;
end;
我认为这里没有“处理得更好”的比较。 Delphi允许您在课堂上放置“普通”和“课堂”成员。以前只能在实例化对象上使用,后者可以在任何地方使用。但这只是Delphi中OO支持的两个部分。
编辑:回答有关速度的问题......
让我们整理一个小测试程序:
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启用优化编译.A / .B / .C调用
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
首先创建对象,并将其地址存储到ebx寄存器中。
要调用tc.A,编译器会在edx中准备参数(42或$ 2A),即eax中'tc'实例的地址,并调用TTestClass.A。
除了取消引用ebx之外,在tc.B情况下几乎相同。
在.A和.B的情况下,eax包含'Self'的值(相当于C ++的'this')。当调用tc.A时,eax包含'tc'实例的地址。当调用tc.B时,eax包含其他东西(我猜它指的是TTestClass的类型信息,但我对此并不十分肯定)。
当代码调用tc.C时,只准备了eax,因为'static'方法不能引用'Self'。
类似的情况发生在TTestClass.B / .C案例中,除了'Self'是从TTestClass typeinfo的??地址从某个常量位置加载的?被储存了。无论如何,当通过实例(tc.B)或通过类(TTestClass.B)调用B时,eax包含相同的值。
所以你可以看到静态调用需要一个'mov'。那是我所提到的无法估量的加速。
答案 1 :(得分:0)
您是说一个实例还是没有实例?
使用第二个示例,您无法实例化它。
我还没有看到有人在生产代码中使用静态类。您仍然可以在第一个示例中声明静态(类)方法。
使用常规类型的类,但声明class var
,class procedure
和class function()
。您可以调用类方法并引用类变量,而无需创建实例。
像这样:
type
TSomeClass = class(TObject)
class var
somevar: String;
class procedure Hello;
end;
请注意,在Delphi 7之后的某个地方添加了类变量,但你绝对应该能够使用类方法。