⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 001.htm

📁 Delphi书籍--Delphi网上教程
💻 HTM
字号:
<HTML><HEAD><meta http-equiv="Content-Type" content="text/html; charset=GB2312"><TITLE>-->DELPHI专题--入门技巧-->Delphi 4增订的Object Pascal</TITLE>
<META NAME="keywords" CONTENT=" DELPHI专题--入门技巧 Delphi 4增订的Object Pascal">
<META NAME="description" CONTENT=" - DELPHI专题--入门技巧 - Delphi 4增订的Object Pascal">

<style>
<!--
#page {position:absolute; z-index:0; left:0px; top:0px}
.tt3 {font: 9pt/12pt "宋体"}
.tt2 {font: 12pt/15pt "宋体"}
a {text-decoration:none}
a:hover {color: blue;text-decoration:underline}
-->
</style>
</HEAD>
<a href="index.html">返回</a>

<body text="#000000" aLink=#9900ff link=#006699 vLink=#006699 bgcolor="#FFFFFF" leftmargin="3" topmargin="3" marginheight="3" marginwidth="3">
<TABLE WIDTH="100%" CELLPADDING=10 CELLSPACING=0 BORDER=0>
<TR>

<TD class="tt2" bgcolor="#F5F8F8" width="84%"><center><B><FONT style="FONT-SIZE: 16.5pt" COLOR="#FF6666" FACE="楷体_GB2312">Delphi 4增订的Object Pascal</FONT></B></center> 
<hr color="#EE9B73" size="1" width="94%"> 
<p class="tt2">本附录在于说明Delphi 4新增订的Object Pascal程式语言。总结来说,Delphi 
4的Object Pascal增订了以下几大部分:<br> 
<br> 
新增加数种内定资料型态。<br> 
<br> 
Dynamic Arrays<br> 
Method and Routine Overloading<br> 
Default Parameters.<br> 
Implementating interfaces by delegation,<br> 
<br> 
可用以下的写法:<br> 
property MyInterface: IMyInterface read FMyInterface <br> 
implements IMyInterface;<br> 
<br> 
新增的内定资料型态<br> 
整数方面:<br> 
<br> 
新增加<i>Int64</i>这种长度六十四位元,范围从-2^63 to 2^63 - 1。<br> 
32-bit unsigned integer新增加<i>Longword</i>型态,范围从0..4294967295。<br> 
<i>Cardinal</i>的范围调整成与上述<i>Longword</i>型态相同。<br> 
<br> 
浮点数方面:<br> 
<i>Real</i>型态基于效率考量,由过去占用48-bit调整成64-bits,<br> 
新增加<i>Real48</i>型态,精确度与过去的<i>Real</i>相同,仍是48-bit。<br> 
<br> 
Dynamic Array<br> 
Delphi 4问世之前,Delphi程式设计师若需要动态长度的阵列,在不得已的情况下,往往采用以下这种「表面上阵列的语法,但实际自己配置管理记忆体」的方式来处理动态阵列:<br> 
#0001 procedure TForm1.Button1Click(Sender: TObject);<br> 
#0002 type<br> 
#0003 TIntegerArray = array[0..0] of integer; <br> 
#0004 PIntegerArray = ^TIntegerArray;<br> 
#0005 var<br> 
#0006 pArrayOfInteger: PIntegerArray; <br> 
#0007 j: integer;<br> 
#0008 begin<br> 
#0009 GetMem(pArrayOfInteger, 10 * SizeOf(Integer)); <br> 
#0010 for j := 0 to 9 do<br> 
#0011 pArrayOfInteger^[j] := j; <br> 
#0012 FreeMem(pArrayOfInteger, 10 * SizeOf(Integer));<br> 
#0013 end;<br> 
<br> 
如果应用Delphi 4新增加的Dynamic Array,则可改用以下的方式:<br> 
<br> 
var MyFlexibleArray: array of Real;<br> 
<br> 
定义之后,以 <i>SetLength</i> 
函数改变阵列实际配置的记忆体大小,例如:<br> 
<br> 
SetLength(MyFlexibleArray, 20); // 0..19<br> 
<br> 
&nbsp;&nbsp;&nbsp; 方便很多,是吗?若想知道Dynamic Array实际长度,请分别以<i>High</i>与<i>Low</i>函数判断,传回「-1」时,表示是一个该阵列的长度为零,例如:<br> 
<br> 
#0001 procedure TForm1.Button2Click(Sender: TObject);<br> 
#0002 var<br> 
#0003 A: array of Integer;<br> 
#0004 begin<br> 
#0005 ShowMessage(IntToStr(High(A))); // <b>-1</b><br> 
#0006 SetLength(A, 3);<br> 
#0007 ShowMessage(IntToStr(High(A))); // 3<br> 
#0008 A := nil;<br> 
#0009 ShowMessage(IntToStr(High(A))); // -1<br> 
#0010 end;<br> 
<br> 
&nbsp;&nbsp;&nbsp; 上述的0008这列,指定<i>nil</i>值将会释放阵列所配置到的记忆。<br> 
&nbsp;&nbsp;&nbsp; 值得注意的是,Compiler对于Dynamic Array并不会自动进行所谓的「Copy-on-Write」。请看以下的程式例:<br> 
<br> 
#0001 procedure TForm1.Button1Click(Sender: TObject);<br> 
#0002 var<br> 
#0003 A, B: array of Integer;<br> 
#0004 begin<br> 
#0005 SetLength(A, 1);<br> 
#0006 A[0] := 1;<br> 
#0007 B := A;<br> 
#0008 B[0] := 2;<br> 
#0009 ShowMessage(IntToStr(A[0])); // ==&gt; 2<br> 
#0010 end;<br> 
<br> 
&nbsp;&nbsp;&nbsp; 0008这列改的虽是<i>B[0]</i>,但Compiler显然还没有聪明到在可能修改阵列内容时,将阵列内容复制一份出来(Copy 
on (possible) Write),于是,0009这列程式显示的结果仍是2。<br> 
于是,若要进行两阵列各索引项目一对一的内容复制,只好自行写回圈一一复制,或者,采用较为简便的写法 
── 呼叫Copy函数:<br> 
<br> 
#0001 procedure TForm1.Button4Click(Sender: TObject);<br> 
#0002 var<br> 
#0003 A, B: array of Integer;<br> 
#0004 begin<br> 
#0005 SetLength(A, 1);<br> 
#0006 A[0] := 1;<br> 
#0007 B := Copy(A, 0, 1);<br> 
#0008 B[0] := 2;<br> 
#0009 ShowMessage(IntToStr(A[0])); // ==&gt; 1<br> 
#0010 ShowMessage(IntToStr(B[0])); // ==&gt; 2<br> 
#0011 end;<br> 
<br> 
&nbsp;&nbsp;&nbsp; 最后,请不要将Dynamic Array与第二章提到的Open Array(开放阵列)搞混了。函式参数的开放阵列,语法虽与Dynamic 
Array差不多,但开放阵列指的是:不限定传入函式的阵列长度,Dynamic 
Array则是指:可变长度的阵列,两者毕竟有所不同。以下是一则我准备的程式范例,不难看出两者之间的差异:<br> 
<b><br> 
#0001 type<br> 
#0002 TDynamicInteger = array of integer;</b><br> 
#0003 <br> 
<b>#0004 procedure Clear_OpenArray(var A: array of Integer);</b><br> 
#0005 var<br> 
#0006 I: Integer;<br> 
#0007 begin<br> 
#0008 for I := 0 to High(A) do A[I] := 0;<br> 
#0009 // SetLength(A, 20); // 不可以这么写<br> 
#0010 end;<br> 
#0011 <br> 
#0012 // 注意, 以下两种写法又有不同喔<br> 
#0013 // I: procedure Clear_DynamicArray(A:TDynamicInteger);<br> 
#0014 // II: procedure Clear_DynamicArray(var A:TDynamicInteger);<br> 
<b>#0015 procedure Clear_DynamicArray(var A: TDynamicInteger);</b><br> 
#0016 var<br> 
#0017 I: Integer;<br> 
#0018 begin<br> 
#0019 for I := 0 to High(A) do A[I] := 0;<br> 
#0020 SetLength(A, 20); // 如果是Dynamic Array, 可以这么写<br> 
#0021 end;<br> 
#0022 <br> 
#0023 procedure TForm1.Button3Click(Sender: TObject);<br> 
#0024 var<br> 
#0025 A: TDynamicInteger;<br> 
#0026 begin<br> 
#0027 SetLength(A, 3);<br> 
#0028 Clear_OpenArray(A);<br> 
#0029 ShowMessage(IntToStr(High(A))); // -1<br> 
#0030 Clear_DynamicArray(A);<br> 
#0031 // 以下这列的结果, 要看 Cleary_DynamicArray的<br> 
#0032 // 参数有没有写 var<br> 
#0033 ShowMessage(IntToStr(High(A)));<br> 
#0034 end;<br> 
<br> 
&nbsp;&nbsp;&nbsp; 请帮我注意0004的<i>Clear_OpenArray</i>,传入的是「由整数构成的阵列,不限定阵列的长度」,0015的<i>Clear_DynamicArray</i>的写法则是「接受一个可变动阵列长度的动态阵列」,若不这样写,当场就变成了开放阵列了。<br> 
<br> 
Method and Routine Overloading<br> 
&nbsp;&nbsp;&nbsp; 所谓的Method Overloading,简单地说:一个以上的函式使用相同的函式名称。这项特性是Object 
Pascal长久以来一直有人想要却一直没有支援的期盼,终于,Delphi 4多了一个保留字:<i>overload</i><b> 
</b>── 相同名称的两个函式,只要在宣告时额外加上<i><b>overload</b></i>,即使函式的参数型态不同,Delphi也会视呼叫当时传入的参数资料型态,决定该呼叫哪一个函式。例如以下这则例子:<br> 
<br> 
#0001 // 两个 Divide 都必须写overload保留字<br> 
#0002 function Divide(X, Y: Double): Double; <b>overload;</b><br> 
#0003 begin<br> 
#0004 Result := X / Y;<br> 
#0005 end;<br> 
#0006 <br> 
#0007 function Divide(X, Y: Integer):Integer;<b>overload;</b><br> 
#0008 begin<br> 
#0009 Result := X div Y;<br> 
#0010 end;<br> 
#0011 <br> 
#0012 procedure TForm1.Button1Click(Sender: TObject);<br> 
#0013 var<br> 
#0014 a, b, c: integer;<br> 
#0015 i, j, k: Double;<br> 
#0016 begin<br> 
#0017 a := 10;<br> 
#0018 b := 3;<br> 
#0019 i := 10;<br> 
#0020 j := 3;<br> 
#0021 c := Divide(a, b);<br> 
#0022 k := Divide(i, j);<br> 
#0023 ShowMessage(IntToStr(c)); // 3<br> 
#0024 ShowMessage(FloatToStr(k)); // 3.333333...<br> 
#0025 end;<br> 
<br> 
&nbsp;&nbsp;&nbsp; 请帮我注意到0002与0007这两列的<i>Divide</i>函数,函数名称相同,但传入的参数型态与函数的传回值并不相同,即使如此,0023与0024呼叫到<i>Divide</i>时,还是会视当时参数的型态型态,决定该呼叫哪一个<i>Divide</i>。<br> 
&nbsp;&nbsp;&nbsp; 
很方便,是吗?有了这项特性,我们就可以写出应用范围更广弹性更大的函数──却不必为每一种情况各自取一个函数名称,同时,这项特性也使得函数呼叫的方式更为一致,真是一项早该支援的特性。除了一般的程序与函数,物件的方法也可以采用<i>overload</i>写法,对于「<i>物件<b>.</b>方法</i>」的撰写与呼叫,肯定更能提供简便与弹性。<br> 
<i>&nbsp;&nbsp;&nbsp; overload</i>可不可以应用在不同的两个单元呢?答案是可以的,但是完全相同的函式宣告不能再写一次。例如上述程式的0007-0010,可以移到其他单元,原来的单元只要<i>uses</i>这个新的单元,函数呼叫时仍然有Overloading的效果。可是,如果将0007-0010的程式码移到其他单元却忘了删除原来位置的程式,换句话说,两个单元各有一个完全长得一样的函式,编译时Delphi就搞不清楚了,结果自然是无法编译。当然啦!同一个单元同一个范围发生这样事也是不许的,各Overloading的函式,在函式宣告上多少总有些不同。<br> 
<br> 
Default Parameters<br> 
<br> 
&nbsp;&nbsp;&nbsp; 
过去,函式如果定义了六个参数,那么,写作函式呼叫的原始码时,就一定得乖乖地传入六个参数,不许多也不许少。若是应用「Default 
Parameters」,可以只传入五个(或者更少)。那...,那其他没给的参数怎么办?没关系,函式内部的程式将自动以预设值代入,稍后我会说明其写法。<br> 
&nbsp;&nbsp;&nbsp; 举例来说,Windows API中有一个蛮好用的函数叫<i>MessageBox</i>,呼叫此函数将出现一通用对话盒,不管是显示讯息或者征询使用者意见,都十分好用。像是以下这道叙述将产生如次页的对话盒,提醒使用者定期备份资料:<br> 
<br> 
Application.MessageBox('程式要结束了喔! 请记得定期备份资料',<br> 
'讯息', MB_OK + MB_ICONINFORMATION);<br> 
<br> 
&nbsp;&nbsp;&nbsp; 
除了显示资料,经由最后一个参数,弹性地搭配各位元旗标,就可以制作出不同按钮的对话盒,询问使用者「是」、「否」、「取消」等简单的问题。<br> 
应用Default Parameters的写法,我们可以写一个类似以下的函数:<br> 
<br> 
#0001 function MyMessageBox(Prompt: string;#0002 <b>Caption: string = '讯息';</b><br> 
#0003 <b>Flag: LongInt = MB_OK +MB_ICONINFORMATION</b>): integer;<br> 
#0004 begin<br> 
#0005 Result := Application.MessageBox(<br> 
#0006 PChar(Prompt), PChar(Caption), Flag);<br> 
#0007 end;<br> 
#0008 <br> 
#0009 procedure TForm1.Button1Click(Sender: TObject);<br> 
#0010 begin<br> 
#0011 MyMessageBox('程式要结束了喔! 请记得定期备份资料');<br> 
#0012 end;<br> 
<br> 
&nbsp;&nbsp;&nbsp; 如此一来,我们既能有一个完整支援<i>MessageBox</i>的函数,只想显示文字时,也能有一个精简型式的函数可用。大家应该明显看得出来:不必写成两个函数。<br> 
观察上述程式的写法,其实也蛮容易的,只不过是在定义函数参数时,一并给定初值。<br> 
不过,实际动手去写时,还是会发现一些限制。继续这个例子来说,参数的预设值一定得是常数,另外,如果某一个参数开始给预设值,接在后头的参数也必须用Default 
Parameters的写法。为什么得有这项限制?以上例来说,如果0001-0003我改成:<br> 
<br> 
#0001 function MyMessageBox(Prompt: string;<br> 
#0002 <b>Caption: string = '讯息';</b><br> 
#0003 <b>Flag: LongInt</b>): integer;<br> 
<br> 
&nbsp;&nbsp;&nbsp; 那么,只传入两个参数进去时,Delphi怎么知道第二个参数该是<i>Captioin</i>或者是「<i>Caption</i>按预设值,第二个参数代入<i>Flag</i>」。Visual 
Basic对此的解法是在呼叫函数时,一并写明各参数名称与值的对应,由于这个缘故,Visual 
Basic甚至允许参数的次序不同也没关系,因为,各参数与其值的对应关系在呼叫函式时已一并注明清楚。很可惜的,Delphi 
4虽有Default Parametets,但还不支援以下的函数呼叫方式:<br> 
<br> 
MyMessageBox('程式要结束了喔! 请记得定期备份资料', Flag = ...);<br> 
<br> 
&nbsp;&nbsp;&nbsp; 
虽然如此,上述「如果某一个参数开始给预设值,接在后头的参数也必须用Default 
Parameters的写法」这项限制,多少还是可以搭配前一节的Overloading加以弥补:<br> 
<br> 
#0001 function MyMessageBox(Prompt: string;<br> 
#0002 Caption: string = '讯息';<br> 
#0003 Flag: LongInt = MB_OK + MB_ICONINFORMATION): integer; overload;<br> 
#0004 begin<br> 
#0005 Result := Application.MessageBox(<br> 
#0006 PChar(Prompt), PChar(Caption), Flag);<br> 
#0007 end;<br> 
#0008 <br> 
<b>#0009 function MyMessageBox(Prompt: string;<br> 
#0010 Flag: LongInt;<br> 
#0011 Caption: string = '讯息'<br> 
#0012 ): integer; overload;</b><br> 
#0013 begin<br> 
#0014 Result := Application.MessageBox(<br> 
#0015 PChar(Prompt), PChar(Caption), Flag);<br> 
#0016 end;<br> 
#0017 <br> 
#0018 procedure TForm1.Button1Click(Sender: TObject);<br> 
#0019 begin<br> 
#0020 MyMessageBox('程式要结束了喔! 请记得定期备份资料');<br> 
#0021 MyMessageBox('别说我没告诉你喔!', MB_OK);<br> 
#0022 end;<br> 
<br> 
(好烦的程式,一再提醒要记得备份。:p)<br> 
<br> 
&nbsp;&nbsp;&nbsp;&nbsp; 请帮我注意这次改写过的程式0009-0012,我重新调整了各参数的次序,并且分别在两同名函数都加上了<i>overload</i>保留字,这样,Delphi就知道该呼叫的是哪一个了。</p> 
<BR> 
<BR> 
<hr color="#EE9B73" size="1" width="94%"> 
 
</TD> 
 
</TR> 
</table> 
</BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -