°ι 、曲 终

深入理解Delphi对象与类

======================================================
注:本文源代码点此下载
======================================================

1.登不了大雅之堂地理解几个概念

说到类和对象,我们不能不提及这样几个概念:类,对象,实例。就我个人觉得可以这样来理解:对象指的是泛称,自然界的任何实体都可以看成一个对象;而类则是以这些对象某些特征而分成的一系列的种类;实例则是特指属于某一个类的一个对象。

好啦,这些大道理我就不用多说了。不如来一个“背道而驰”的作法,我们用delphi code 来阐述这些外国人提出的一些令我们中国人不好理解的概念吧:

var

abtn:tbutton;

定义abtn是属于tbutton类的一个对象,但abtn不能说是一个实例,因为它还没有创建,所以我们说这是定义了一个对象,如果说定义了一个实例,多多少少有

一些不够确切。:)

begin

abtn:=tbutton.create(self);//创建一个tbutton的实例

abtn.caption:='对象';

abtn.free;

end;

2.对象是一个地地道道的指针

从物理角度来看,对象就是一段地址空间,这段地址空间的标志就是我们定义的类“变量”。所以我们可以把对象看成一个类的指针。大家知道,要访问一个指针就

必须对指针初始化。对象的既然是一个指针,也必须对它进行初始化。如何初始化呢?

还是说指针的初始化吧。对于一个指针可以有以下两种方法来进行初始化:

(一)直接分配

var

pint:^integer;

begin

new(pint);

pint^:=12;

dispose(pint);

end;

(二)指向别的已分配空间的变量

var

pint:^integer;

i:integer;

begin

i:=12;

pint:=@i;

end;

有趣的是,对象这种“指针”也有两种方法初始化

(一)直接分配

var

aform:tform;

begin

aform:=tform.create(self);

aform.showmodal;

aform.free;

end;

(二)指向别的已分配空间的实例

var

aform:tform;

begin

aform:=self;

aform.caption:='知道了吗?为什么会这样呢';

end;

file://这个aform和它所指向的form实例共用同一段地址单元,所有对aform操作都将反应

file://到它所对应的form实例之上。

说到这,我们就很好解释为什么过程(函数)的对象参数传递时,象这样这的格式:

(一)procedure setedit(var edit:tedit);

begin

edit.text:='11';

end;

(二)procedure setedit(edit:tedit);

begin

edit.text:='11';

end;

效果是一样的了。(一)是把一个tedit实体作为参数引用的形式进行参数传递,(二)是把一个tedit的对象“指针”作为参数传递。

3.类可以理解成一种特殊的数据类型

我们知道数据类型可以进行强制类型转化,类即然可以理解成一种数据类型,那么它也应该可以进行类类型转。比方如下代码为一个按钮(button1)的单击事件:

(一)

代码

procedure tform1.button1click(sender: tobject);

var

acaption:string;

begin

acaption:=tbutton(sender).caption;//sender从tobject转化到tbutton

showmessage(format('you clicked ''%s'' !',[acaption]));

end;

在这段代码中,sender是一个tobject型对象,我们把它强制转化为tbutton类型。如你看得不清楚,可以参照一下我们通常的数据类型的转化:

(二)

代码

procedure tform1.button1click(sender: tobject);

var

s_str:string;

p_str:pchar;

begin

s_str:='i love china!';

p_str:=pchar(s_str);

s_str:='';

s_str:=string(p_str);

showmessage(s_str);

end;

但是在面对对象的程序设计过程中,强调的是安全性,如(一)的强制类型转化存在着不安全性。如下的代码,依然是写button1.onclick事件:

(三)

procedure tform1.button1click(sender: tobject);

begin

tcanvas(sender).brush.color:=clred;

end;

执行一下,就会出错。这样岂不是违背了面对对象的程序设计的宗旨了吗?没有,即然是类,就应该有类特定的类强制转化方法,改(三)的方法如下:

(四)

procedure tform1.button1click(sender: tobject);

begin

(sender as tcanvas).brush.color:=clred;

end;//用as来转化,as就可以把错误抓住,不会影响程序的正常运行。

说到这我顺便提一下vb吧,如果学过vb的人可能觉得其中的控件数组比较爽,尤其是在编写象计算器这样的程序时。但delphi给我们什么呢?答案是delphi也能快速简洁的开发出这样的程序。如是操作:在窗体上放一个edit和十个button,把button.caption分别设为'0','1','2',...'9',然后写一个按钮的onclick事件如下:

(五)

procedure tform1.button1click(sender: tobject);

begin

edit1.text:=edit1.text+(sender as tbutton).caption;

end;

把别的button的onclick事件都关联到button1click上,运行程序。拍拍手!这样计算器程序的雏形就具备了。我们用delphi的类类型转化,开发出来类似vb中的控件数组功能的程序也是很棒的嘛!:)

4.抽象类和它的实例

delphi中有一种类为抽象类,你不能天真的直接为它创建一个实例。如:tstrings类。如下代码:

(一)

var

strlst:tstrings;

begin

strlst:=tstrings.create;

strlst.add('i love japan!');

strlst.free;

end;

这是不对的。那如何为诸如tstrings这样的抽象类构造实例呢?答案是借助它的非抽象子类。我们知道tstrings有一个tstringlist非抽象子类。我们就可以这样作:

(二)

var

strlst:tstrings;

begin

strlst:=tstringlist.create;//借助其子类的构造器,对strlst进行子类化

strlst.add('i love china!');

strlst.free;

end;

(三)

var

strlst:tstringlist;

begin

strlst:=tstringlist.create;

file://放弃吧,不要再用抽象类,完全用它的“儿子”来你的事吧

strlst.add('i love china!');

strlst.free;

end;

5.类是一种对数据和操作高度的封装机制

(一)数据封装

代码

unit unit2;

interface

type

temployee=class

private

fname:string;

public

constructor create;

functiongetname:string;

procedure setname(aname:string);

end;

implementation

{ temployee }

constructor temployee.create;

begin

fname:='blazingfire';

end;

function temployee.getname: string;

begin

result:=fname;

end;

procedure temployee.setname(aname: string);

begin

fname:=aname;

end;

end.

如上代码,我们就用了一个过程setname和一个函数getname对私有变量fname进行完全的封装。我们要对fname操作就只有这样:

代码

uses

unit2;

procedure tform1.button1click(sender: tobject);

var

aemployee:temployee;

begin

aemployee:=temployee.create;

aemployee.setname('rose');//利用setname来设置fname

messagebox(handle,pchar(aemployee.getname),'empoyee',0);

file://用getname来访问fname

aemployee.free;

end;

(二)操作封装

代码

unit unit2;

interface

type

tdivision=class

public

file://多态性让你的程序更据有“柔韧性”

function getdiv(num1,num2:double):double;overload;

function getdiv(num1,num2:integer):integer;overload;

end;

implementation

{ division }

function tdivision.getdiv(num1, num2: double): double;

begin

try

result:=num1/num2;

except

result:=0;//提供弹形处理机制,处理除数为0情况

end;

end;

function tdivision.getdiv(num1, num2: integer): integer;

begin

try

result:=num1 div num2;

except

result:=0;//提供弹形处理机制,处理除数为0情况

end;

end;

end.

如上代码我们通过类的多态性机制把除法分别处理成整除和非整除,又通过异常处理屏去除数为0的情况,从而保证操作的安全性,在调用时,我们就可以这样来:

代码

uses

unit2;

{$r *.dfm}

procedure tform1.button1click(sender: tobject);

var

division:tdivision;

ivalue:integer;

fvalue:double;

begin

division:=tdivision.create;

ivalue:=division.getdiv(1,2);

fvalue:=division.getdiv(1.0,2);

ivalue:=division.getdiv(1,0);

fvalue:=division.getdiv(1.0,0);

division.free;

end;

6.类是一种代码重用机制

比方在5中我们想对这个类加上一个getadd函数来作加法运算就可以用类的继承。如下写就可以了:

(一)

代码

unit unit2;

interface

type

tdivision=class

public

function getdiv(num1,num2:double):double;overload;

function getdiv(num1,num2:integer):integer;overload;

end;

type

toperation=class(tdivision)

public

function getadd(num1,num2:double):double;

end;

implementation

{ division }

function tdivision.getdiv(num1, num2: double): double;

begin

try

result:=num1/num2;

except

result:=0;

end;

end;

function tdivision.getdiv(num1, num2: integer): integer;

begin

try

result:=num1 div num2;

except

result:=0;

end;

end;

{ toperation }

function toperation.getadd(num1, num2: double): double;

begin

result:=num1+num2;

end;

end.

这里我们从tdivision继承了一个子类toperation。toperation就可以即有tdivsion公有方法getdiv,又有自己的独特的方法getadd。这是类为我们提供的“鱼和熊掌兼得”之法。不错吧。:)


======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值