(delphi11最新学习资料) Object Pascal 学习笔记---第8章第6节(安全类型转换运算符)

8.6 安全类型转换运算符

​ 正如我们之前所见,子类的语言类型兼容性规则允许你在期望祖先类的地方使用子类。如我所提到的,反向则不可能。

​ 现在假设TDog类有一个Eat方法,而TAnimal类中不存在此方法。如果变量FMyAnimal引用了一个狗,你可能希望能够调用这个函数。但如果你尝试调用,而变量指向的是另一个类,结果就会出错。通过显式类型转换,我们可能会导致令人讨厌的运行时错误(或者更糟糕的是,出现微妙的内存覆盖问题),因为编译器无法确定对象的类型是否正确,以及我们调用的方法是否确实存在。

​ 为了解决这个问题,我们可以使用基于运行时类型信息的技术。从本质上讲,因为每个对象在运行时“知道”自己的类型和父类。我们可以使用is运算符或使用TObject类的一些方法询问此信息。is运算符的参数是一个对象和一个类类型,返回值是一个布尔值:

if FMyAnimal is TDog then...

​ 只有当 FMyAnimal 对象当前引用的是 TDog 类对象或 TDog 的子类且与 TDog 兼容时,is 表达式才会返回 True。这意味着,如果测试存储在 TAnimal 变量中的 TDog 对象是否真的是 TDog 对象,测试将会成功。换句话说,如果可以安全地将对象 (FMyAnimal) 赋值给数据类型 (TDog) 的变量,则该表达式的值为 True。

注解: 实际上,is 运算符的实现是由 TObject 类的 InheritsFrom 方法提供的。因此,您可以将相同的表达式写为 FMyAnimal.InheritsFrom(TDog)。直接使用这个方法的原因是它还可以应用于类引用和不支持 is 运算符的其他特殊类型。

现在您确信动物是一只狗后,可以通过以下代码使用直接类型转换(通常是不安全的):
if FMyAnimal is TDog then
beginMyDog := TDog(FMyAnimal);Text := MyDog.Eat;
end;

​ 同样的操作也可以直接通过另一个相关的类型转换运算符 as 来完成。as 仅在请求的类与实际类兼容时才转换对象,否则将导致运行时异常。as 运算符的参数是一个对象和一个类类型,结果是一个“转换”为新的类类型的对象。我们可以编写以下片段:

MyDog := FMyAnimal as TDog;
Text := MyDog.Eat;

如果只想调用 Eat 函数,还可以使用更简洁的表示法:

(FMyAnimal as TDog).Eat;

​ 这个表达式的结果是一个 TDog 类数据类型的对象,因此您可以对其应用该类的任何方法。传统转换和使用 as 转换的区别在于,后者会检查对象的实际类型,并在类型与试图转换的类型不兼容时引发异常。引发的异常是 EInvalidCast(下一章将介绍异常)

警告:相比之下,在 C# 语言中,如果对象与类型不兼容,则 as 表达式将返回 nil,而直接类型转换将引发异常。因此,基本上这两个操作与 Object Pascal 相比是相反的。

​ 要避免这种异常,请使用 is 运算符,如果成功,则进行普通类型转换(实际上,没有理由连续使用 isas,进行两次类型检查,尽管通常会看到它们的组合使用):

if FMyAnimal is TDog thenTDog(MyAnimal).Eat;

​ 在 Object Pascal 中,这两个类型转换运算符非常有用,因为您通常希望编写可用于相同类型或不同类型的多个组件的通用代码。例如,当将组件作为参数传递给事件响应方法时,使用通用数据类型(TObject)时,通常需要将其转换回原始组件类型:

procedure TForm1.Button1Click(Sender: TObject);
beginif Sender is TButton then...
end;

这是一种常用技术,我将在后面的示例中使用它(事件将在第 10 章中介绍)。

​ 这两个类型转换运算符 isas 非常强大,您可能会被诱使将其视为标准的编程构造。尽管它们确实很强大,但您可能应该将它们的使用限制在特殊情况下。当您需要解决涉及多个类的复杂问题时,请首先尝试使用多态。只有在特殊情况下,多态无法应用时,才应尝试使用类型转换运算符来作为补充。

注意:使用类型转换操作符会对性能产生轻微的负面影响,因为它必须遍历类的层次结构,以查看类型转换是否正确。正如我们所看到的,虚拟方法调用只需要查找内存,速度要快得多。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/794895.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

苹果CMSV10整合dplayer播放器增加记忆+P2P播放+自动下一集功能插件详细保姆级教程

1.本站已打包&#xff0c;可以直接下载然后上传到你服务器的苹果CMS网站static/player目录下就可以了&#xff0c;下面是教程 wlm3u8.js代码&#xff1a; MacPlayer.Html <iframe border"0" src"mac<span class"wp_keywordlink"><a hre…

全国航空机场分布矢量数据/旅游景点poi/全国港口码头分布/地铁站分布/火车站分布/POI矢量数据

民用航空机场是指针对包括跑道型机场、表面直升机场、高架直升机场、船上直升机场、直升机水上平台、滑翔机场、水上机场、有人操纵气球施放场以及其他专供民用航空器起降的划定区域。民用航空机场分为通用航空机场和公共运输机场&#xff1b;不包括临时机场和专用机场。 根据中…

SSM项目实战——哈哈音乐(四)前台模块开发

1、项目准备 ①导入依赖和前端资源 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.x…

课时86:流程控制_函数基础_函数退出

2.1.2 函数退出 这一节&#xff0c;我们从 基础知识、简单实践、小结 三个方面来学习。 基础知识 简介 我们可以将函数代码块&#xff0c;看成shell脚本内部的小型脚本&#xff0c;所以说函数代码块也会有执行状态返回值。对于函数来说&#xff0c;它通常支持两种种状态返回…

已解决java.lang.NegativeArraySizeException: 负数组大小异常的正确解决方法,亲测有效!!!

已解决java.lang.NegativeArraySizeException: 负数组大小异常的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 目录 问题分析 报错原因 解决思路 解决方法 检查并修正硬编码值 调整计算逻辑 校验变量值 总结 博主v&#xff1a;XiaoMing_Jav…

解决element-plus table组件 fixed=“right“(left)浮动后横向滚动文字穿透的问题

BUG 版本&#xff1a;element-plus 2.6.1 浏览器&#xff1a;360极速浏览器22.1 (Chromium内核) 组件&#xff1a;el-table组件 问题&#xff1a;在头部/尾部浮动加上斑马条纹后&#xff0c;横向滚动存在文字穿透的问题。具体如图&#xff1a; 白色背景行的文字&#xff0c…

反转链表(leetcode 206)

迭代核心逻辑&#xff1a; 原链表的新的下一个结点&#xff0c;作为新反转链表的头结点 代码分析&#xff1a; 初始化prev为nullptr&#xff08;之后是作为反转后链表的最后一个结点&#xff09;&#xff0c; 遍历原链表时保存当前结点的下一个结点&#xff0c;将curr的nex…

蓝桥杯单片机真题实践篇

这里就不完全写思路过程代码什么的&#xff0c;这一篇文章就写我在训练真题中遇到的过程。 &#xff08;呜呜呜&#xff0c;时间不够辣&#xff0c;能做多少算多少吧....&#xff09; 十三届省赛题 问题1&#xff1a;数码管的数字消影不明显 &#xff08;参考&#xff1a;蓝…

【蓝桥杯-单链表-网络寻路】

蓝桥杯-单链表-网络寻路 单链表基本操作操作一&#xff1a;向链表头插入一个数操作二:在第 k个插入的数后插入一个数操作三&#xff1a;删除第 k个插入的数后面的一个数&#xff1b; P8605 [蓝桥杯 2013 国 AC] 网络寻路 单链表基本操作 初始化有关操作 // head 表示头结点的…

python-基础篇-字符串、列表、元祖、字典-列表

文章目录 2.3.2列表2.3.2.1列表介绍2.3.2.1.1列表的格式2.3.2.1.2打印列表 2.3.2.2列表的增删改查2.3.2.2.1列表的遍历2.3.2.2.1.1使用for循环2.3.2.2.1.2使用while循环 2.3.2.2.2添加元素("增"append, extend, insert)2.3.2.2.2.1append 2.3.2.2.2.2extend2.3.2.2.2…

GPS经纬度坐标转换

在淘宝买的ATGM336H 用串口工具在室外读取了下面的数据 这些字符串是GPS定位设备输出的NMEA 0183格式的数据。 NMEA 0183是一种用于在船舶、飞机和其他移动设备中传输位置、速度和时间等信息的标准协议。 $BDGSV,39,,,27*62 22:29:38.654 $GNRMC,142939.000,A,3036.7460,K,A*…

考研回忆录【二本->211】

备考时长差不多快一年半&#xff0c;从22年的11月底开始陆陆续续地准备考研&#xff0c;因为开始的早所以整个备考过程显得压力不是很大&#xff0c;中途还去一些地方旅游&#xff0c;我不喜欢把自己绷得太紧。虽然考的不是很好&#xff0c;考完我甚至都没准备复试&#xff0c;…

12-1-CSS 常用样式属性

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 CSS 常用样式属性1 CSS 三角形2 CSS 用户界面样式2.1 什么是界面样式2.2 鼠标…

微电网优化:基于​海象优化算法(Walrus Optimization Algorithm,WOA)​的微电网优化(提供MATLAB代码)

一、微电网优化模型 微电网是一个相对独立的本地化电力单元&#xff0c;用户现场的分布式发电可以支持用电需求。为此&#xff0c;您的微电网将接入、监控、预测和控制您本地的分布式能源系统&#xff0c;同时强化供电系统的弹性&#xff0c;保障您的用电更经济。您可以在连接…

(学习日记)2024.04.02:UCOSIII第三十节:信号量

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

数据库之DDL操作(数据库,表,字段)

Data Definition Language&#xff0c;数据库定义语言&#xff0c;用来定义数据库对象&#xff08;数据库&#xff0c;表&#xff0c;字段&#xff09; 1.数据库操作 1.1查询所有数据库 show databases; 1.2查询当前数据库 show databases(); 1.3创建数据库 create da…

Ps:预览调整 32 位 HDR 图像

由于 HDR 图像的动态范围超出了标准计算机显示器的显示范围。在 Photoshop 中打开 HDR 图像时&#xff0c;图像可能会非常暗或出现褪色现象。 Photoshop 提供了专门的预览调整功能&#xff0c;以使标准显示器显示的 HDR 图像的高光和阴影不会太暗或出现褪色现象。 预览调整设置…

docker的安装及入门指令

目录 一、将docker安装到云服务器步骤 1.更新系统yum版本 2.安装所需依赖 3.添加docker仓库设置(使用的是阿里云) 4.安装docker引擎 5.启动docker并开启自动启动 6. 检查是否安装成功&#xff0c;成功会显示相应版本&#xff0c;否则安装失败 二、docker常用命令 1.从…

最优算法100例之33-数据流的中位数

专栏主页:计算机专业基础知识总结(适用于期末复习考研刷题求职面试)系列文章https://blog.csdn.net/seeker1994/category_12585732.html 题目描述 中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。 例如, [2,3,4] 的中位数是 3 [2,3] 的中位…

Map源码解析

基本介绍 其实HashMap底层是个什么东西我们之前也讲过, 就是一个哈希桶(差不多可以看成一个数组), 然后每一个节点又连接着链表/红黑树之类的, 下面让我们看一看具体在源码上是怎样实现的: 常量及其它 -> static final int DEFAULT_INITIAL_CAPACITY 1 << 4; //这个…