CnPack Forum


 
Subject: Delphi面向对象学习随笔二:编写第一个类
bahamut8348
灌水司司长
Rank: 6Rank: 6


UID 4743
Digest Posts 14
Credits 337
Posts 79
点点分 337
Reading Access 10
Registered 2007-1-18
Status Offline
Post at 2008-6-20 15:10  Profile | Blog | P.M. 
Delphi面向对象学习随笔二:编写第一个类

这回,我们讨论怎么编写我们自己的第一个类。
    在编写我们自己的类之前,首先要说的是“类的继承”。
    记得前几天,我在和一个朋友讨论类的特点的时候,他说:“类是可以没有构造方法的!”其实类必须有至少一个构造方法的,但是他的话也不全错,可以理解成“我们可以不实现我们自己的构造方法”。
    当我们没有显式的为类编写一个构造方法的时候,那么,看上去,这个类好象是没有构造方法,但是实际上,就算你没有为这个类编写一个属于你自己的构造方法的时候,该类还是有构造方法的;为什么呢?因为,在你选定父类并从父类派生(继承)一个新的后代类的时候,首先,编译器会COPY一份父类中“可继承”的数据成员到新的子类中。
    那么,什么是可继承的数据成员呢,我们来看下面的代码:

  TPersistent = class(TObject)
  private
    procedure AssignError(Source: TPersistent);
  protected
    procedure AssignTo(Dest: TPersistent); virtual;
    procedure DefineProperties(Filer: TFiler); virtual;
    function  GetOwner: TPersistent; dynamic;
  public
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); virtual;
    function  GetNamePath: string; dynamic;
  end;

上面是VCL内部TPersistent类的声明代码,我们可以看到几个关键字private、protected、public,这几个关键字是说明数据成员的访问限制的,其中:

  private:        存在于该访问限制下的数据成员只能被本类所访问。
  protected:    存在于该访问限制下的数据成员只能被本类及后代类所访问。
  public:          存在于该访问限制下的数据成员可以被任何类访问。
  published:     存在于该访问限制下的数据成员的访问限制与public一样,但是在本域下的属性将会在注册类的时候被注册给IDE。
  automated:   存在于该访问限制下的数据成员为自动成员,常用于定义嵌入(OLE)自动化类型信息的公共接口。 PS: 该域并不常用,这里不做介绍

    由此可见,所谓的“可继承”部分是指除"private"域指定的数据成员。
    回到上面的问题,由于在继承新类的时候,编译器会COPY一份父类所有可继承部分的数据成员到新的子类中,当没有为新类编写构造方法时,新类会调用父类的构造方法,如果父类中也没有编写构造方法,那么将层层上溯,直到根类TObject中。
    就像上面的类,我们可以看到,在类里面的确是没有重写新的构造方法,但是这个类的构造方法却是真实的存在的。

    现在,我们可以开始编写第一个属于我们自己的简单的类了:

type // 说明我们从这里开始往下要声明的是自定义的数据类型
  TNewClass = class(TPersistent)
    // TNewClass   新类的类名
    // TPersistent 父类的类名
  private
    // 私有域数据成员
  protected
    // 保护域数据成员
  public
    // 公共域数据成员
    procedure SayHello(); // 我们为类添加的新的方法
  published
  end; // 类的声名结束

implementation // 实现部分

procedure TNewClass.SayHello;
  // SayHello 方法的实现部分
begin
  ShowMessage('Hello');
end;

至此,我们完成了一个简单的类的编写。
    我们可以写一段简单的代码来测试类的工作情况:

var
  NewClass: TNewClass; // 定义一个类 TNewClass 的对象 NewClass
begin
  NewClass:= TNewClass.Create; // 为对象 NewClass 分配内存空间,并创建它
  NewClass.SayHello(); // 调用 SayHello 方法
  NewClass.Free; // 销毁对象并释放对象的内存空间
end;

有时,我们会看到这样的声明方式:

type
  TNewClass = class
    ...
  end;

这是一种省略父类的声明方式,当省略了父类的时候,DELPHI编译器会把根类TObject当做新类的基类,和

type
  TNewClass = class(TObject)
    ...
  end;

效果一样,这里我推荐下面的方式,因为这样可以让代码更清晰。

[ 本帖最后由 bahamut8348 于 2008-6-20 15:12 编辑 ]




做人要厚道,看帖要回贴
Top
shenloqi
灌水处处长
Rank: 4



UID 34
Digest Posts 1
Credits 287
Posts 179
点点分 287
Reading Access 10
Registered 2003-3-15
Status Offline
Post at 2008-6-23 11:51  Profile | P.M. 
automated域只是为了向后兼容,所以可以不必要了解。

巴哈说:
    由此可见,所谓的“可继承”部分是指除"private"域指定的数据成员。
    回到上面的问题,由于在继承新类的时候,编译器会COPY一份父类所有可继承部分的数据成员到新的子类中。

理解上是可以这么理解的,但是实际上,即使是private的部分数据,子类也是从父类继承到的。
Top
Passion (LiuXiao)
管理员
Rank: 9Rank: 9Rank: 9


UID 359
Digest Posts 19
Credits 6758
Posts 3555
点点分 6758
Reading Access 102
Registered 2004-3-28
Status Offline
Post at 2008-6-23 12:10  Profile | Blog | P.M. 
估计是可继承与可“视”继承的字眼问题。
Top
 




All times are GMT++8, the time now is 2024-4-27 08:52

    本论坛支付平台由支付宝提供
携手打造安全诚信的交易社区 Powered by Discuz! 5.0.0  © 2001-2006 Comsenz Inc.
Processed in 0.007471 second(s), 7 queries , Gzip enabled

Clear Cookies - Contact Us - CnPack Website - Archiver - WAP