DELPHI面向对象参考

DELPHI面向对象参考

陈奇 2005-07-21

一、类和对象

类是对象的类型,是创建对象的模板。一个类可以创建多个对象,而一个对象总是属于某个类。类具有内部的属性(状态)和行为(操作)。

对象是类的实例,具有区别于同类其他对象的属性集合。

对象的声明存放于堆栈,对象的引用存放于堆。

二、类的方法分类

1、  普通方法

不加任何修饰的方法为普通方法。普通方法必须调用类的实例进行访问。即必须

建类的对象,调用方式为:对象.方法,声明方式为:

procedure[function] 方法名(参数表)[:返回值];

2、  构造方法

构造方法用于创建类的实例,调用后返回类的句柄。构造方法可以有多个版本。声明方式是:

          constructor 构造方法名(参数表);

3、  析构方法

析构方法用于销毁类的实例,一般不建议直接调用析构方法,而采用调用对象.Free的方式进行对象释放。声明方式为:

destructor 析构方法名(参数表);

4、  类方法

类方法属于一个类,在运行时即存在于内存中。可使用类.方法的方式进行调用,即不需要创建类的实例。声明方式是在普通方法前加class

class procedure[function] 方法名(参数表)[:返回值];

5、  消息处理方法

消息处理方法和一个唯一的消息ID进行关联,用于响应动态分派的消息。声明方式:

procedure 方法名(消息变元);message 消息ID;

三、多态、继承、重载

1、  静态方法

静态方法由对象的类决定。属于“早期联编”,即在编译阶段就决定了方法的实现版本。一个类的实例可创建为其他类的实例,但是调用到同名方法时,使用的方法是声明该实例的类的静态方法,声明方式:

procedure[function] 方法名(参数表)[:返回值];

2、  虚拟方法

虚拟方法可实现“后期联编”,即在程序运行时可动态调用不同的方法版本,实现多态。所有类的虚拟方法在内存中建立了一张VMT(虚拟方法表),在调用时动态定位方法函数的位置。比动态方法多占用内存空间,但是速度较快。声明方式:

procedure[function] 方法名(参数表)[:返回值];virtual;

3、  动态方法

虚拟方法可实现“后期联编”,即在程序运行时可动态调用不同的方法版本,实现多态。本类的动态方法在内存中建立了一个DMT(动态方法表),在调用时根据动态方法唯一的编号定位方法地址。比虚拟方法少占用内存,但是速度较慢(因为可能用到祖先类的动态方法)。声明方式:

procedure[function] 方法名(参数表)[:返回值];dynamic;

4、  抽象方法

抽象方法不提供方法的实现脚本。只提供一个方法的签名(方法名称、参数表、返回值)。一般在高级别类中使用抽象方法。派生类对抽象方法进行覆盖、重载实现抽象方法脚本。使用抽象方法,必须创建实现了抽象方法的类(一般为派生类)才可使用。因为抽象方法也属于“后期联编”,因此必须和虚拟方法、动态方法结合,声明方式:

procedure[function] 方法名(参数表)[:返回值];virtual;abstract;

procedure[function] 方法名(参数表)[:返回值];dynamic; abstract;

抽象方法提供了一种从高层次视图观察对象的方式

5、  方法覆盖

在父类中生命的静态方法、虚拟方法、动态方法,都可在派生类中进行同名签名登记。这将覆盖父类的这些方法。提供更特殊的功能,声明方式:

procedure[function] 方法名(参数表)[:返回值];override;

方法的覆盖提供了对类的多态性

6、  方法重载

在父类中生命的静态方法、虚拟方法、动态方法,都可在派生类中进行同名签名登记,但是需要不同的参数表。这将重载父类的这些方法。提供更特殊的功能,声明方式:

procedure[function] 方法名(参数表)[:返回值];overload;

方法的重载提供了对类的扩充性

四、reintroduceselfisas

1、  reintroduce

当父类中以定义了一方法,派生类再定义同签名的方法将会隐藏父类的方法,如果不希望这种结果出现,可在派生类定义方法时,加此标志,声明方式:

procedure[function] 方法名(参数表)[:返回值];reintroduce;

2、  self

self代表了实例对象自身。类的所有数据成员和函数成员都隐含存在于with self do结构范围内。使用方法:

self.Edit1.text:=’’;

3、  is

is用于进行实例对象的类型检查,以Boolean返回是否是该类实例(或派生类实例),使用方法:

if Edit1 is Tedit then …

4、  as

as用于进行对象的强制类型转换,一般适用于子类向父类的转换(特殊→一般),而从父类到子类的转换可能失败。在使用时,可结合is进行判断,使用方式:

if Sender is Tedit then (Sender as TEdit).Text:=’’;

五、类内部成员可见性

1、  类具有privatepublicprotectedpublished4中访问属性。访问属性是指其他类对该类对象的可操作性,可读写性,以及其他类对本类中类方法(函数)的可操作性

2、  private:本类内部使用;声明在同一单元的其他类可使用

3、  public:本类、本类派生类、其他类都可访问

4、  protected:本类、本类派生类可访问。其他类不可访问

5、  published:所有类都可访问。

综合举例:

TClass1=class

private

  {内部数据/状态储存声明}

  FName: string;

  FAge: Integer;

  {内部属性写方法声明}

  procedure SetAge(const Value: Integer);

protected

  {保护虚方法声明}

  procedure Eat;virtual;

public

  {公有属性/状态储存声明}

  Sex: string;

published

  {公共属性发布声明}

  {构造函数}

  constructor create;

  {具有读/写方法的属性声明}

  property Name:string read FName write FName;

  property Age: Integer read FAge write SetAge;

end;

TClass2=class

private

  FSex: string;

published

  constructor create;

end;

TClass11=class(TClass1)

public

  {覆盖了父类中同名的方法,提升了方法的可见性}

  procedure Eat;override;

end;

 

{ TClass1 }

 

constructor TClass1.create;

begin

end;

 

procedure TClass1.Eat;

begin

 

end;

 

procedure TClass1.SetAge(const Value: Integer);

begin

  FAge := Value;

end;

 

{ TClass2 }

 

constructor TClass2.create;

var

  c2:TClass2;

begin

  c2:=TClass2.create;

  c2.FSex:='';

  FreeAndNil(c2);

end;

 

{ TClass11 }

 

procedure TClass11.Eat;

begin

  inherited;

 

end;

 

UML-类图:

6、  派生类可提升父类的可见性,却不可降低父类的可见性

六、对象、对象引用、类引用、参数传递

1、  对象之间通过消息传递(参数),进行互操作,使用其他类提供的服务(方法组合);消息即对另一对象方法的调用或属性读写

2、  对象分配在堆中、普通数据类型分配在栈中

3、  对象名代表了该对象在栈中的位置,该位置存储的是对象在堆中的实际地址;普通变量名代表了该变量在栈中的位置,该位置存储的是具体数据,而该数据可能是其他变量/对象的地址

4、  值参传递:传递的是具体的数值,进行处理后不会改变原值,其实传递的是该数据的一个副本

5、  引用传递:传递的是对该变量/对象的地址引用,处理后可能会改变原值,传递的是同一个变量/对象的地址

6、  类引用:类的类,形式为“class of type”,其中type代表该类可引用的类元类型。

七、对象的创建、使用、销毁

1、  创建:Create Tobject提供的默认构造函数,若从Tobject继承创建的类,自动继承该方法

2、  销毁:DestroyTobject提供的默认析构函数,若从Tobject继承创建的类,自动继承该方法

3、  使用:可使用if Assigned (对象名) 判断该对象是否存在;使用FreeAndNil(对象名)释放对象

4、  克隆:继承自Tpersistent的类对象都具有克隆功能。使用对象2.Assign(对象1)的方式克隆

5、  对象的属主:当对象拥有属主时,其生命周期由属主对象进行管理,无属主的对象需要进行手工管理。

6、  对象的创建:先继承父类创建,再完成自身的创建

7、  对象的释放:先释放自身,在完成父类的继承释放

八、类及对象间的关系

1、  继承:子类继承了父类的所有保护、公有、发布部分的数据成员及函数/过程成员

2、  重载:不是类的特有。提供一个同名但参数不同的函数/过程,具有多个实现版本

3、  覆盖:子类通过继承父类的函数/过程,重新定义了功能实现

4、  引用:一个对象内部定义了另一个对象变量,即为引用关系

5、  合成:对象内的各组成部分依赖于某一主体属性而同生共灭

6、  聚合:对象内的各组成部分属于零散的简单组合关系,使用不同的服务组合成一个整体的功能

九、接口

1、  接口:具有某种特定的属性及函数/过程签名的定义,而没有实现。不具备内部数据成员。功能的调用是通过创建实现其功能签名的派生类完成的

2、  接口必须具备3个方法:_AddRef/_Release/QueryInterface,最简单的方式是从TinterfacedObject继承

3、  接口使用演示:

IInterface=interface

['{02960574-2025-46C3-9882-F79C3C67EA99}']

  function GetName:string;

  procedure Eat;

end;

 

TPerson=class(TInterfacedObject,IInterface)

private

  FName: string;

public

  function GetName:string;virtual;

  procedure Eat;dynamic;

  procedure SayHello;virtual;abstract;

published

  constructor create;

  destructor destory;

  property Name:string read FName write FName;

end;

 

TChinese=class(TPerson,IInterface)

public

  procedure SayHello(str:string);overload;

  procedure SayHello;overload;override;

published

  constructor create;

  destructor destory;

end;

 

{ TPerson }

 

constructor TPerson.create;

begin

  ShowMessage('TPerson.create');

end;

 

destructor TPerson.destory;

begin

  ShowMessage('TPerson.destory');

end;

 

procedure TPerson.Eat;

begin

  ShowMessage('TPerson.Eat');

end;

 

function TPerson.GetName: string;

begin

  result:='TPerson.GetName';

end;

 

{ TChinese }

 

procedure TChinese.SayHello(str: string);

begin

  ShowMessage('TChinese.SayHello('+str+')');

end;

 

constructor TChinese.create;

begin

  ShowMessage('TChinese.create');

end;

 

destructor TChinese.destory;

begin

  ShowMessage('TChinese.destory');

end;

 

procedure TChinese.SayHello;

begin

  //inherited;

  ShowMessage('TChinese.SayHello');

end;

 

procedure TForm1.Button2Click(Sender: TObject);

var

  FMan:TPerson;

begin

  FMan:=TChinese.create;

  FMan.SayHello;

  FMan.Free;

end;

4、   

十、 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一个使用ADO连接池的示例,演示了TADOStoredProc动态参数的使用,带重连机制 =================== unit UnitDemo; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm2 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form2: TForm2; //数据库服务器 gDBServer: String = '127.0.0.1'; //数据库名称 gDBName: String = 'master'; //数据库用户名 gDBUser: String = 'sa'; //密码 gDBPass: String = '2001'; implementation {$R *.dfm} uses ADODB, UnitADOConnectionPool; const CreateSQL = 'create procedure TestMyPool (@type sysname) '#13#10+ 'as'#13#10+ 'select * from sysobjects where xtype=@type'#13#10+ 'return @@rowcount'; DeleteSQL = 'if Exists(select 1 from sysobjects where xtype=N''P'' and name=N''TestMyPool'')'#13#10+ ' drop procedure TestMyPool'; var gPoolMan: TADOConnPoolMan = Nil; procedure TForm2.Button1Click(Sender: TObject); var ADOObject:TADOConnPoolObject; ADOStoredProc:TADOStoredProc; Running :Integer; I: Integer; begin //取得一个存储过程资源(含一数据库有效连接) ADOObject := gPoolMan.CreateSP('TestMyPool'); if ADOObject = Nil then //取得资源失败 Exit; try ADOStoredProc := ADOObject.ExecObject as TADOStoredProc; Running := 2;//允许重试(两次)操作,以便在操作失败之后达到重连 while Running>0 do begin Dec(Running); if ADOObject.NeedRefresh then begin//判断是否有重连标志(比如数据库断开等,可能需要进行重连) if Not ADOObject.Reconnect then Exit; ADOObject.NeedRefresh := Not ADOStoredProc.Parameters.Refresh; if ADOObject.NeedRefresh then Exit; end; for I := 1(*Zero is the *Result* Parameter*) to ADOStoredProc.Parameters.Count - 1 do begin //========================= //传递参数 ADOStoredProc.Parameters.Items[I].Value := 'U'; //========================= end; if Running 0 then try //执行存储过程 ADOStoredProc.Open; //执行存储过程成功,退出循环进入后续的数据处理 break; except On E:Exception do begin //执行失败非程序级的异常通常有两种可能: //1.数据库连接断开 //2.自适合的参数传递当中可能存储过程已更新,参与不一致 //设置重连标志 ADOObject.NeedRefresh := True; //=================== //这里记录数据库操作失败日志 //=================== end; end; Exit; end; //========================== //从ADOStoredProc当中读取记录 ShowMessage(IntToStr(ADOStoredProc.Parameters.ParamByName('Result').Value)); //========================== //关闭存储对象的资源 ADOStoredProc.Close; finally //调用结束,释放资源 ADOObject.Free; end; end; procedure TForm2.FormCreate(Sender: TObject); var ADOConn:TADOConnection; begin (****************BEGIN*******************) (*注:仅为测试准备 *) //初始化测试环境 ADOConn := Nil; if Not TADOConnPoolMan.ConnectADO( gDBServer,gDBUser,gDBPass,gDBName,true,ADOConn) then Exit; try ADOConn.Execute(DeleteSQL); ADOConn.Execute(CreateSQL); finally try ADOConn.Close; except end; ADOConn.Free; end; (*****************END********************) //初始化连接池 gPoolMan := TADOConnPoolMan.Create(gDBServer,gDBUser,gDBPass,gDBName,true); end; procedure TForm2.FormDestroy(Sender: TObject); var ADOConn:TADOConnection; begin //释放连接池 if Assigned(gPoolMan) then gPoolMan.Free; (****************BEGIN*******************) (*注:仅为测试准备 *) //清理测试环境 ADOConn := Nil; if Not TADOConnPoolMan.ConnectADO( gDBServer,gDBUser,gDBPass,gDBName,true,ADOConn) then Exit; try ADOConn.Execute(DeleteSQL); finally try ADOConn.Close; except end; ADOConn.Free; end; (*****************END********************) end; end.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值