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)的单击事件:
(一)

ExpandedBlockStart.gif 代码
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类型。如你看得不清楚,可以参照一下我们通常的数据类型的转化:
(二)

ExpandedBlockStart.gif 代码
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.类是一种对数据和操作高度的封装机制
(一)数据封装

ExpandedBlockStart.gif 代码
unit  Unit2;

interface
type
   TEmployee
= class
   
private
     FName:String;
   
public
     Constructor Create;
     
function    GetName: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操作就只有这样:

ExpandedBlockStart.gif 代码
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 ;

 


(二)操作封装

ExpandedBlockStart.gif 代码
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的情况,从而保证操作的安全性,在调用时,我们就可以这样来:

ExpandedBlockStart.gif 代码
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函数来作加法运算就可以用类的继承。如下写就可以了:
(一)

ExpandedBlockStart.gif 代码
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。这是类为我们提供的“鱼和熊掌兼得”之法。不错吧。:)

转载于:https://www.cnblogs.com/rogee/archive/2010/09/20/1832000.html

你可能感兴趣的:(Delphi中的类和对象)