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

📄 047.htm

📁 delphi教程
💻 HTM
📖 第 1 页 / 共 5 页
字号:
face="Arial" size="3">protected</font><font face="宋体" lang="ZH-CN" size="3">部分,你能使用</font><font
face="Arial" size="3">protected</font><font face="宋体" lang="ZH-CN" size="3">声明定义开发者的接口。也就是说。对象的用户不能访向</font><font
face="Arial" size="3">protected</font><font face="宋体" lang="ZH-CN" size="3">部分,但开发者通过继承就可能做到,这意味着你能通过</font><font
face="Arial" size="3">protected</font><font face="宋体" lang="ZH-CN" size="3">部分的可访问性使部件编写者改变对象工作方式,而又不使用户见到这些细节。</p>
<p>  ⑶</font><font face="Arial" size="3"> </font><font face="宋体" lang="ZH-CN"
size="3">定义运行时接口</p>
<p>  将对象的某一部分定义为</font><font face="Arial" size="3">public</font><font
face="宋体" lang="ZH-CN" size="3">可使任何代码访问该部分。如果你没有对域方法或属性加以</font><font
face="Arial" size="3">private</font><font face="宋体" lang="ZH-CN" size="3">、</font><font
face="Arial" size="3">protected</font><font face="宋体" lang="ZH-CN" size="3">、</font><font
face="Arial" size="3">public</font><font face="宋体" lang="ZH-CN" size="3">的访问控制描述。那么该部分就是</font><font
face="Arial" size="3">published</font><font face="宋体" lang="ZH-CN" size="3">。</p>
<p>  因为对象的</font><font face="Arial" size="3">public</font><font
face="宋体" lang="ZH-CN" size="3">部分可在运行时为任何代码访问,因此对象的</font><font
face="Arial" size="3">public</font><font face="宋体" lang="ZH-CN" size="3">部分被称为运行接口。运行时接口对那些在设计时没有意义的项目,如依靠运行时信息的和只读的属性,是很有用的。那些设计用来供用户调用的方法也应放在运行时接口中。</p>
<p>  下例是一个显示两个定义在运行时接口的只读属性的例子:</p>
<p> </font><font face="Arial" size="3"></p>
<p>type </p>
<p>TSampleComponent = class(TComponent)</p>
<p>private</p>
<p>FTempCelsius: Integer; { </font><font face="宋体" lang="ZH-CN" size="3">具体实现是</font><font
face="Arial" size="3">private } </p>
<p>function GetTempFahrenheit: Integer; </p>
<p>public</p>
<p>property TempCelsius: Integer read FTempCelsius; { </font><font face="宋体"
lang="ZH-CN" size="3">属性是</font><font face="Arial" size="3">public }</p>
<p>property TempFahrenheit: Integer read GetTempFahrenheit; </p>
<p>end; </p>
<p> </p>
<p>function GetTempFahrenheit: Integer; </p>
<p>begin </p>
<p>Result := FTempCelsius * 9 div 5 + 32; </p>
<p>end;</p>
<p> </font><font face="宋体" lang="ZH-CN" size="3"></p>
<p>  既然用户在设计时不能改变</font><font face="Arial" size="3">public</font><font
face="宋体" lang="ZH-CN" size="3">部分的属性的值,那么该类属性就不能出现在</font><font
face="Arial" size="3">Object Inspector</font><font face="宋体" lang="ZH-CN" size="3">窗口中。</p>
<p>  ⑷</font><font face="Arial" size="3"> </font><font face="宋体" lang="ZH-CN"
size="3">定义设计时接口</p>
<p>  将对象的某部分声明为</font><font face="Arial" size="3">published</font><font
face="宋体" lang="ZH-CN" size="3">,该部分也即为</font><font face="Arial"
size="3">public</font><font face="宋体" lang="ZH-CN" size="3">且产生运行时类型信息。但只有</font><font
face="Arial" size="3">published</font><font face="宋体" lang="ZH-CN" size="3">部分定义的属性可显示在</font><font
face="Arial" size="3">Object Inspector</font><font face="宋体" lang="ZH-CN" size="3">窗口中。对象的</font><font
face="Arial" size="3">published</font><font face="宋体" lang="ZH-CN" size="3">部分定义了对象的设计时接口。设计时接口包含了用户想在设计时定制的一切特征。</p>
<p>  下面是一个</font><font face="Arial" size="3">published</font><font
face="宋体" lang="ZH-CN" size="3">属性的例子,因为它是</font><font
face="Arial" size="3">published</font><font face="宋体" lang="ZH-CN" size="3">,因此可以出现在</font><font
face="Arial" size="3">Object Inspector</font><font face="宋体" lang="ZH-CN" size="3">窗口:</p>
<p> </font><font face="Arial" size="3"></p>
<p>TSampleComponent = class(TComponent) </p>
<p>private </p>
<p>FTemperature: Integer; { </font><font face="宋体" lang="ZH-CN" size="3">具体实现是</font><font
face="Arial" size="3"> private }</p>
<p>published</p>
<p>property Temperature: Integer read FTemperature write FTemperature; { </font><font
face="宋体" lang="ZH-CN" size="3">可写的</font><font face="Arial" size="3"> } </p>
<p>end;</p>
<p> </font><font face="宋体" lang="ZH-CN" size="3"></p>
<p>  </font><font face="Arial" size="3">3. </font><font face="宋体" lang="ZH-CN"
size="3">派送方法</p>
<p>  派送</font><font face="Arial" size="3">(Dispatch)</font><font face="宋体"
lang="ZH-CN" size="3">这个概念是用来描述当调用方法时,你的应用程序怎样决定执行什么样的代码,当你编写调用对象的代码时,看上去与任何其它过程或函数调用没什么不同,但对象有三种不同的派送方法的方式。</p>
<p>  这三种派送方法的类型是:</font><font face="Arial" size="3"></p>
<p></font><font face="宋体" lang="ZH-CN" size="3"> </font><font face="Arial" size="3">
</font><font face="宋体" lang="ZH-CN" size="3">●</font><font face="Arial" size="3"> </font><font
face="宋体" lang="ZH-CN" size="3">静态的</p>
<p> </font><font face="Arial" size="3"> </font><font face="宋体" lang="ZH-CN" size="3">●</font><font
face="Arial" size="3"> </font><font face="宋体" lang="ZH-CN" size="3">虚拟的</p>
<p> </font><font face="Arial" size="3"> </font><font face="宋体" lang="ZH-CN" size="3">●</font><font
face="Arial" size="3"> </font><font face="宋体" lang="ZH-CN" size="3">动态的</p>
<p> </p>
<p>  虚方法和动态方法的工作方式相同,但实现不同。两者都与静态方法相当不同。理解各种不同的派送方法对创建部件是很有用的。</font><font
face="Arial" size="3"></p>
<p></font><font face="宋体" lang="ZH-CN" size="3"> ⑴</font><font face="Arial"
size="3"> </font><font face="宋体" lang="ZH-CN" size="3">静态方法:</p>
<p>  如果没有特殊声明,所有的对象方法都是静态的</font><font
face="Arial" size="3">.</font><font face="宋体" lang="ZH-CN" size="3">。静态方法的工作方式正如一般的过程和函数调用。在编译时,编译器决定方法地址,并与方法联接。</p>
<p>  静态方法的基本好处是派送相当快。因为由编译器决定方法的临时地址,并直接与方法相联。虚方法和动态方法则相反,用间接的方法在运行时查找方法的地址,这将花较长的时间。</p>
<p>  静态方法的另一个不同之处是当被另一类型继承时不做任何改变,这就是说如果你声明了一个包含静态方法的对象,然后从该对象继承新的对象,则该后代对象享有与祖先对象相同的方法地址,因此,不管实际对象是谁,静态方法都完成相同的工作。</p>
<p>  你不能覆盖静态方法,在后代对象中声明相同名称的静态方法都将取代祖先对象方法。</p>
<p>  在下列代码中,第一个部件声明了两静态方法,第二个部件,声明了相同名字的方法取代第一个部件的方法。</p>
<p> </p>
<p></font><font face="Arial" size="3">type </p>
<p>TFirstComponent = class(TComponent) </p>
<p>procedure Move; </p>
<p>procedure Flash; </p>
<p>end;</p>
<p> </p>
<p>TSecondComponent = class(TFirstComponent) </p>
<p>procedure Move; { </font><font face="宋体" lang="ZH-CN" size="3">尽管有相同的声明,但与继承的方法不同</font><font
face="Arial" size="3"> } </p>
<p>function Flash(HowOften: Integer): Integer; { </font><font face="宋体" lang="ZH-CN"
size="3">同</font><font face="Arial" size="3">Move</font><font face="宋体" lang="ZH-CN"
size="3">方法一样</font><font face="Arial" size="3"> } </p>
<p>end;</p>
<p> </font><font face="宋体" lang="ZH-CN" size="3"></p>
<p>  ⑵</font><font face="Arial" size="3"> </font><font face="宋体" lang="ZH-CN"
size="3">虚方法</p>
<p>  调用虚方法与调用任何其它方法一样,但派送机制有所不同。虚方法支持在后代对象中重定义方法,但调用方法完全相同,虚方法的地址不是在编译时决定,而是在运行时才查找方法的地址。</p>
<p>  为声明一个新的方法,在方法声明后增加</font><font face="Arial"
size="3">virtual</font><font face="宋体" lang="ZH-CN" size="3">指令。方法声明中的</font><font
face="Arial" size="3">virtual</font><font face="宋体" lang="ZH-CN" size="3">指令在对象虚拟方法表(</font><font
face="Arial" size="3">VMT</font><font face="宋体" lang="ZH-CN" size="3">)中创建一个入口,该虚拟方法表保存对象类所有虚有拟方法的地址。</p>
<p>  当你从已有对象获得新的对象,新对象得到自己的</font><font
face="Arial" size="3">VMT</font><font face="宋体" lang="ZH-CN" size="3">,它包含所有的祖先对象的</font><font
face="Arial" size="3">VMT</font><font face="宋体" lang="ZH-CN" size="3">入口,再增加在新对象中声明的虚拟方法。后代对象能覆盖任何继承的虚拟方法。</p>
<p>  覆盖一个方法是扩展它,而不是取代它。后代对象可以重定义和重实现在祖先对象中声明的任何方法。但无法覆盖一个静态方法。覆盖一个方法,要在方法声明的结尾增加</font><font
face="Arial" size="3">override</font><font face="宋体" lang="ZH-CN" size="3">指令,在下列情况,使用</font><font
face="Arial" size="3">override</font><font face="宋体" lang="ZH-CN" size="3">将产生编译错误:</font><font
face="Arial" size="3"></p>
<p></font><font face="宋体" lang="ZH-CN" size="3"> </font><font face="Arial" size="3">
</font><font face="宋体" lang="ZH-CN" size="3">●</font><font face="Arial" size="3"> </font><font
face="宋体" lang="ZH-CN" size="3">祖先对象中不存在该方法</font><font
face="Arial" size="3"></p>
<p></font><font face="宋体" lang="ZH-CN" size="3"> </font><font face="Arial" size="3">
</font><font face="宋体" lang="ZH-CN" size="3">●</font><font face="Arial" size="3"> </font><font
face="宋体" lang="ZH-CN" size="3">祖先对象中相同方法是静态的</p>
<p> </font><font face="Arial" size="3"> </font><font face="宋体" lang="ZH-CN" size="3">●</font><font
face="Arial" size="3"> </font><font face="宋体" lang="ZH-CN" size="3">声明与祖先对象的(如名字、参数)不匹配</p>
<p> </p>
<p>  下列代码演示两个简单的部件。第一个部件声明了三个方法,每一个使用不同的派送方式,第二个部件继承第一个部件,取代了静态方法,覆盖了虚拟方法和动态方法。</p>
<p> </p>
<p></font><font face="Arial" size="3">type </p>
<p>TFirstComponent = class(TCustomControl)</p>
<p>procedure Move; { </font><font face="宋体" lang="ZH-CN" size="3">静态方法</font><font
face="Arial" size="3"> } </p>
<p>procedure Flash; virtual; { </font><font face="宋体" lang="ZH-CN" size="3">虚</font><font
face="Arial" size="3"> </font><font face="宋体" lang="ZH-CN" size="3">方</font><font
face="Arial" size="3"> </font><font face="宋体" lang="ZH-CN" size="3">法</font><font
face="Arial" size="3"> } </p>
<p>procedure Beep; dynamic; { </font><font face="宋体" lang="ZH-CN" size="3">动态虚拟方法</font><font
face="Arial" size="3"> } </p>
<p>end;</p>
<p> </p>
<p>TSecondComponent = class(TFirstComponent) </p>
<p>procedure Move; { </font><font face="宋体" lang="ZH-CN" size="3">声明了新的方法</font><font
face="Arial" size="3"> } </p>
<p>procedure Flash; override; { </font><font face="宋体" lang="ZH-CN" size="3">覆盖继承的方法</font><font
face="Arial" size="3"> }</p>
<p>procedure Beep; override; { </font><font face="宋体" lang="ZH-CN" size="3">覆盖继承的方法</font><font
face="Arial" size="3"> } </p>
<p>end;</p>
<p> </font><font face="宋体" lang="ZH-CN" size="3"></p>
<p>  ⑶</font><font face="Arial" size="3"> </font><font face="宋体" lang="ZH-CN"
size="3">动态方法</p>
<p>  动态方法是稍微不同于虚拟方法的派送机制。因为动态方法没有对象</font><font
face="Arial" size="3">VMT</font><font face="宋体" lang="ZH-CN" size="3">的入口,它们减少了对象消耗的内存数量。派送动态方法比派送一般的虚拟方法慢。因此,如果方法调用很频繁,你最好将其定义为虚方法。</p>
<p>  定义动态方法时,在方法声明后面增加</font><font face="Arial"
size="3">dynamic</font><font face="宋体" lang="ZH-CN" size="3">指令。</p>
<p>  与对象虚拟方法创建入口不同的

⌨️ 快捷键说明

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