Delphi高手突破第二章,2,对象大小,类方法与类引用,错误的面向对象设计

================Delphi对象所占内存空间大小==============================

对象所占的内存空间大小取决于这个对象中的数据成员,加上一个4字节的VMT,成员函数不占空间。

注意:编译器对于无法合并的小于32位空间的数据域填充到32位大小,以加快存取速度。所以两个16位的word会被合并成一个integer。但一个单独16位的word会被扩展成一个integer

procedure TForm1.Button1Click(Sender: TObject);

var

Obj : TMyClass;

begin

Obj := TMyClass.Create();

with memo1.Lines do

begin

Add('对象大小:' + IntToStr(Obj.InstanceSize));

Add('对象所在地址 :' + IntToStr(Integer(Obj)));

Add('FMember1所在地址:' + IntToStr(Integer(@Obj.FMember1)));

Add('FMember2所在地址:' + IntToStr(Integer(@Obj.FMember2)));

Add('FMember3所在地址:' + IntToStr(Integer(@Obj.FMember3)));

Add('FMember4所在地址:' + IntToStr(Integer(@Obj.FMember4)));

end;

Obj.Free();

end;

======================类方法和类引用================================

1. 定义类方法(静态方法),它无法操作对象的数据成员,加上class关键字:

class function TObject.ClassName: ShortString;

构造函数 create其实就是一个类方法。

2. 定义类引用(元类,更抽象):

TMyClass = class;

TMyClassClass = class of TMyClass; // TMyClassClass就是类引用

用法:

TMyClass = class;

public

class procedure Show(); // 类方法

end;

TMyClassClass = class of TMyClass;

var

MyClass : TMyClassClass;

MyObj: TMyClass;

begin

MyObj := MyClass.Create();// 注意:引用类MyClass直接调用了类方法。其作用与MyObj := TMyClass.Create(); 完全相同

MyClass.Show();

MyObj.Free();

end;

主要用作类型参数化上,因为有时候在编译时无法得知某个对象的具体类型,而要调用其类方法(如构造函数),此时可以将类型作为一个参数来传递。

比如:Application.CreateForm(TForm1, Form1);

procedure TApplication.CreateForm(

// TComponentClass = class of TComponent; 类引用类型

InstanceClass: TComponentClass;

var Reference

);

允许在运行期确定类型,可以给程序带来莫大的灵活性。

3. Self代表类,因此可以调用类方法,但不能访问对象数据成员

class function ClassMethod1(): integer;

调用的时候可以 self.ClassMethod1();

====================面向对象的错误用法==================================

1. 定义一堆系统函数在一个类里。

其实它什么都没有封装,只是一堆函数的集合而已,是一个没有状态(数据成员)的类。

它不是活的,它所生成的每个对象之间没有任何差别。

2. 如果只有Get/Set函数的类,还是称不上类。

虽然状态是活的,但实际上什么没有隐藏任何东西,也没有简化任何东西。这样的类与record没有任何区别。

什么是设计优良的类?

一个文件操作类:具有状态信息,接口简单、明了、易用。它封装了所有对文件操作的算法,客户端程序不必限于复杂的文件操作的代码中。