2010-04-10 73 views
2

有人告诉我不止一次德尔福使用以下处理动态类优于static.Thereby:是否真的比静态更好地处理动态类?

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%的类的项目我的工作在有和只需要一个实例。我真的必须使用第一种方式来使用这些类吗?是否更好地优化,由德尔福处理?

对不起,我没有任何参数来支持这个假设,但我想要专家的意见。

在此先感谢!

+2

您应该避免在第二个示例中访问someint,因为它仅在之前实例化该类时才有效。也许你忘了把它标记为一个类变量?除此之外,向公众展示一个班级领域只是对我看起来不对。 – 2010-04-10 10:19:23

+0

是的,我忘记把它变成一个类变量,但我记住了它。但这里的问题不是'是这个OO'。我写了一个样本类,你揭露了这个领域是正确的,但为什么没有人回答主要问题? – 2010-04-10 11:22:01

+0

“我被告知”:**由谁**?那些人在什么情况下提出这一要求?他们提供了任何证据吗? – 2010-04-11 02:55:03

回答

11

如果您创建的类只包含类变量和类方法,那么您可以在不实例化的情况下使用它。即在你的第二个例子中,你可以使用Tsomeclass.proc2(但不是Tsomeclass.someint,因为这个变量没有像Uwe指出的那样用'class'前缀标记)。

对于(难以分辨的小)速度差异,您还可以将您的类方法标记为“静态”。

type 
    TSomeclass = class 
    class procedure proc2; static; 
    end; 

在我看来这里没有“处理更好”的比较。德尔福允许你把'普通'和'班'成员放在课堂上。前者只能用于实例化的对象,后者则可以在任何地方使用。但这只是Delphi中面向对象支持的两个部分。

编辑:要回答关于速度的问题...

让我们把一个小的测试程序:

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. 

德尔福2010年启用优化编译.A/.B/.C电话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 

该对象首先被创建并且其地址被存储到ebx寄存器中。

要调用tc.A,编译器在edx中准备参数(42或$ 2A),即eax中'tc'实例的地址并调用TTestClass.A。

在tc.B情况下几乎发生同样的情况,除了ebx被解除引用。在.A和.B情况下,eax包含'Self'的值(相当于C++的'this')。当tc.A被调用时,eax包含'tc'实例的地址。当调用tc.B时,eax包含其他内容(我猜它指向的是TTestClass的类型信息,但我不确定)。

当代码调用tc.C时,只有eax准备好了,因为'static'方法不能引用'Self'。

类似的情况发生在TTestClass.B/.C情况下,除了当'Self'从TTestClass类型信息的地址的某个常量位置被加载时。被储存了。无论如何,当通过实例(tc.B)或通过类(TTestClass.B)调用B时,eax包含相同的值。

所以你可以看到静态调用需要一个'mov'少。那是我所指的可以加速的加速。

+0

但你说速度,我不明白。第一种方法(在我的问题中)比你的方式(类方法+静态和没有实例)更快? – 2010-04-10 10:43:20

+0

另请参阅Delphi的简介第二章:http://oreilly.com/catalog/delphi/chapter/ch02.html – gabr 2010-04-10 19:53:30

0

你是说一个实例还是没有实例?

你的第二个例子,你不能实例化。

我还没有看到任何人在生产代码中使用静态类。您仍然可以在第一个示例中声明静态(类)方法。

使用常规类型的类,但声明class var,class procedureclass function()。您可以调用类方法并引用类变量而不创建实例。

像这样:

type 
    TSomeClass = class(TObject) 
    class var 
     somevar: String; 
    class procedure Hello; 
    end; 

注进行了德尔福7之后某处补充说,类变量,但你一定要能够做到类方法。

+0

目前有一个实例,但是如果它们是静态的,那么就没有。 – 2010-04-10 10:08:49

+0

为什么第一个例子?如果我不启动它,我可以使用TsomeClass.proc1或TSomeClass.proc2.Could你请回答主要问题 - 什么是更有效率,更好的优化和更好地处理德尔福? – 2010-04-10 10:40:14

+0

@John,是的。你可以使用类方法和变量而不用实例化一个对象,就像'TSomeClass.proc1()'一样。 – 2010-04-10 10:42:33