(delphi11最新学习资料) Object Pascal 学习笔记---第8章第1节(继承)

第8章 继承

​ 如果说编写类的关键原因是封装,那么在类之间使用继承的关键原因就是灵活性。将这两个概念结合起来,你就能拥有可以使用且不会改变的数据类型,并能创建这些类型的修改版本,这就是最初所谓的 “开放-封闭原则”:

“软件实体(类、模块、函数等)应该开放以进行扩展,但封闭以进行修改。”

​ ——Bertrand Meyer,《面向对象软件构造》,1988年

​ 诚然,继承是一种非常强的约束,会导致代码的紧密耦合,这是现在不推荐的做法,但继承也为开发人员提供了巨大的能力(是的,同时也带来了更多的责任)。

​ 在此,我不想就这一特性展开讨论,而是想向大家介绍类型继承的工作原理,特别是在 Object Pascal 语言中的工作原理。

8.1 从现有类型继承

​ 我们经常需要使用我们自己编写或别人给我们的现有类的略有不同的版本。

​ 例如,您可能需要添加一个新方法或对现有方法稍作修改。除非你想在不同情况下使用该类的两个不同版本,否则你可以通过修改原始代码来轻松实现。此外,如果该类最初是由其他人编写的(而你是从库中找到的),你可能希望将自己的修改分开。

​ 如果一个类有两个相似的版本,一种典型的老式方法是复制原始类型定义,修改代码以支持新特性,然后给生成的类取一个新名字。这种方法也许可行,但也可能带来问题:在复制代码的同时,也复制了错误;当其中一份代码中的错误被修复后,你必须记得将修复应用到另一份代码中;如果你想添加一个新特性,你需要添加两次或更多次,这取决于你随着时间推移所复制的原始代码的数量。即使在第一次编写代码时这样做不会拖慢您的速度,但这种方法对于软件维护来说却是一场灾难。此外,这种方法会导致两种完全不同的数据类型,因此编译器无法帮助您利用两种类型之间的相似之处。

​ 为了解决表达类之间相似性时出现的这类问题,Object Pascal 允许你直接从已有的类定义一个新类。这种技术被称为继承(或子类化,或类型派生),是面向对象编程语言的基本要素之一。

​ 要从现有类继承,只需在子类声明的开头注明该类即可。实际上,每次创建新窗体时,系统都会自动执行这一操作:

typeTForm1 = class(TForm)...end;

​ 这个简单的定义表示 TForm1 类继承了 TForm 类的所有方法、字段、属性和事件。您可以将 TForm 类的任何公共方法应用于 TForm1 类型的对象。反过来,TForm 又从另一个类继承了一些方法,依此类推,直到 TObject 类(它是所有类的基类)。相比之下,C++、C#和Java可能会使用类似以下的语法:

class Form1: TForm
{
...
}

​ 作为演示继承的一个简单示例,我们可以对上一章的 ViewDate 示例稍作修改,从 TDate 派生一个新类,并修改其中的一个函数 GetText。你可以在 DerivedDates 示例的 Dates.pas 文件中找到这段代码。

typeTNewDate = class(TDate)publicfunction GetText: string;end;

​ 在本例中,TNewDate 是派生自 TDate 的。通常可以说 TDate 是 TNewDate 的祖先类、基类或父类,而 TNewDate 是 TDate 的子类、后代类或子类。

​ 为了实现新版本的 GetText 函数,我使用了 FormatDateTime 函数,该函数使用(除其他功能外)预定义的月份名称。下面是 GetText 方法,其中 "dddddd"代表长日期格式:

function TNewDate.GetText: string;
beginResult := FormatDateTime('dddddd', FDate);
end;

​ 定义新类后,我们需要在 DerivedDates 项目的窗体代码中使用这种新数据类型。只需定义 TNewDate 类型的 ADay 对象,并在 FormCreate 方法中调用其自定义类型的构造函数即可:

typeTDateForm = class(TForm)...privateFDay: TNewDate; // 更新声明end;procedure TDateForm.FormCreate(Sender: TObject);
beginFDay := TNewDate.Create; // 更新行DateLabel.Text := FDay.GetText;
end;

​ 无需任何其他更改,新的应用程序就能正常运行。

​ TNewDate 类继承了增加日期、添加天数等方法。此外,调用这些方法的旧版代码仍可正常工作。实际上,要调用新版本的 GetText 方法,我们不需要修改源代码!Object Pascal 编译器会自动将调用绑定到一个新方法上。

​ 所有其他事件处理器的源代码完全保持不变,尽管其含义发生了很大变化,正如新的输出所演示的那样(见图 8.1)。

图8.1: DerivedDates程序的输出,其中月份和日期的名称取决于Windows区域设置

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

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

相关文章

备考ICA----Istio实验10---为单个主机配置TLS Istio Ingress Gateway实验

备考ICA----Istio实验10—为单个主机配置 TLS Istio Ingress Gateway实验 1. 环境准备 部署httpbin kubectl apply -f istio/samples/httpbin/httpbin.yaml 2. 证书生成 2.1 生成根证书 生成根证书keyfile和crt文件 mkdir example_certs_root openssl req -x509 -sha256 …

强化基础-Java-泛型

什么是泛型? 泛型其实就参数化类型,也就是说这个类型类似一个变量是可变的。 为什么会有泛型? 在没有泛型之前,java中是通过Object来实现泛型的功能。但是这样做有下面两个缺陷: 1 获取值的时候必须进行强转 2 没有…

学透Spring Boot — 创建一个简单Web应用

从今天开始,我们将开始学习一个新的系列,那就是在项目中用得非常广泛的一个框架 —— Spring Boot,我们会循序渐进地介绍 Spring Boot 的方方面面,包括理论和实战,也会介绍和Spring Boot一些热点面试题。 概论 本文是…

C#学生信息成绩管理系统

一、系统功能描述 本系统包括两类用户:学生、管理员。管理员可以通过系统来添加管理员信息、修改管理员信息、添加学生信息、修改学生信息;开设课程、查询课程、录入成绩、统计成绩、修改成绩、修改个人密码等,而学生则可以通过系统来选择课…

观察者模式和发布-订阅模式有什么异同

观察者模式(Observer Pattern)和发布-订阅模式(Publish-Subscribe Pattern)都是用于处理对象之间的一对多依赖关系,但它们在实现方式和应用场景上有一些异同。 观察者模式: 观察者模式定义了一种一对多的依…

基于Givens旋转完成QR分解进而求解实矩阵的逆矩阵

基于Givens旋转完成QR分解进而求解实矩阵的逆矩阵 目录 前言 一、Givens旋转简介 二、Givens旋转解释 三、Givens旋转进行QR分解 四、Givens旋转进行QR分解数值计算例子 五、求逆矩阵 六、MATLAB仿真 七、参考资料 总结 前言 在进行QR分解时,HouseHolder变换…

YOLOv8项目实践——目标检测、实例分割、姿态估计、目标追踪算法原理及模型部署(Python实现带界面)

简介 Ultralytics YOLOv8是一种前沿的、最先进的(SOTA)模型,它在前代YOLO版本的成功基础上进行了进一步的创新,引入了全新的特性和改进,以进一步提升性能和灵活性。作为一个高速、精准且易于操作的设计,YO…

量化交易入门(二十三)什么是MTM指标,原理是什么

MTM指标全称是Momentum指标,翻译为动量指标。它用来衡量市场价格在一定时间内上涨或下跌的幅度,属于趋势型指标。其计算公式是: MTM(N) 当前收盘价 - N日前的收盘价 其中N表示统计的周期数,常用参数有6日、12日和24日。 MTM指标的应用要点如下: 判断趋势强弱:MTM数值越大,表…

uniapp 微信小程序 canvas 手写板文字重复倾斜水印

核心逻辑 先将坐标系中心点通过ctx.translate(canvasw / 2, canvash / 2) 平移到canvas 中心,再旋转设置水印 假如不 translate 直接旋转,则此时的旋转中心为左上角原点,此时旋转示意如图所示 当translate到中心点之后再旋转,此…

树状打印二叉树的类Java、Go、PHP

说明和效果 树的结构示例:1/ \2 3/ \ / \4 5 6 7树状打印二叉树Java代码 static class TreeNode {int val 0;TreeNode left null;TreeNode right null;public TreeNode(int val) {this.val val;}}//打印二叉树的类// TreeOperation.javastati…

P8649 [蓝桥杯 2017 省 B] k 倍区间:做题笔记

目录 思路 代码思路 代码 推荐 P8649 [蓝桥杯 2017 省 B] k 倍区间 思路 额嗯,这道题我刚上来是想到了前缀和,但是还要判断每个子序列,我就两层for嵌套,暴力解了题。就是我知道暴力肯定过不了但是写不出来其他的[留下了苦…

【ESP32S3 Sense接入语音识别+MiniMax模型对话】

1. 前言 围绕ESP32S3 Sense接入语音识别MiniMax模型对话展开,首先串口输入“1”字符,随后麦克风采集2s声音数据,对接百度在线语音识别,将返回文本结果丢入MiniMax模型,进而返回第二次结果文本,实现语言对话…

Serilog日志框架

文章目录 一. Serilog介绍1.1 安装Serilog1.2 Serilog日志级别 二. Serilog.App项目应用2.1 Serilog一般应用2.2 兼容系统日志 三. Serilog.Web应用3.1 Minimal示例3.2 WebApi示例 参考链接 一. Serilog介绍 Serilog 是 .NET应用程序的诊断日志记录库。它易于设置,…

libVLC 动态视频壁纸

在 Windows 上,你可能需要使用 Windows API 来设置壁纸,而在 Linux 上,你可能需要使用某种桌面环境特有的方法。在 macOS 上,这一功能可能受到限制。 效果图如下所示: 以下是一个简单的示例,说明了如何在 …

Ubuntu16.04 切换系统python和gcc版本

4.切换系统python版本 sudo update-alternatives --config python5.切换系统gcc版本 sudo update-alternatives --config gccubuntu16.04中的gcc版本及版本切换 5.查看opencv版本 pkg-config opencv --modversion查看cuda版本 cat /usr/local/cuda/version.txt或者 nvcc …

[Qt] QString::fromLocal8Bit 的使用误区

QString::fromLocal8Bit 是一个平台相关的函数。默认情况下在 Windows 下 就是 gbk 转 utf-8 ,在 Linux就应该是无事发生。因为Linux平台默认的编码方式就是 utf-8 可以通过 void QTextCodec::setCodecForLocale(QTextCodec *c)来修改 Qt默认的编码方式。如下 第一输出乱码的…

【单调队列单调栈专题】【蓝桥杯备考训练】:矩形牛棚、单调栈、滑动窗口、子矩阵、最大子序和、烽火传递【已更新完成】

目录 1、矩形牛棚(usaco training 6.1) 思路: 预处理的过程: 判断左右边界的过程: 代码: 2、单调栈(单调栈模板) 思路: 基本步骤: 1、维护单调性 2、处理要求…

vue组件如何使用?

今天我随便试两个组件 第一个轮播图 在minn.js 引入 import { createApp } from vue; import { Swipe, SwipeItem } from vant; const app createApp(); app.use(Swipe); app.use(SwipeItem); <van-swipe class"my-swipe" :autoplay"3000" indica…

python学习15:python中的input语句

python中的input语句 我们前面学习过print语句&#xff0c;可以将内容输出到屏幕上&#xff1b;在python中&#xff0c;与之对应的还有一个input语句&#xff0c;用来获取键盘输入。 数据输出&#xff1a;print 数据输入&#xff1a;input 使用上也很简单&#xff1a; 使用inp…

jvm高级面试题-2024

说下对JVM内存模型的理解 JVM内存模型主要是指Java虚拟机在运行时所使用的内存结构。它主要包括堆、栈、方法区和程序计数器等部分。 堆是JVM中最大的一块内存区域&#xff0c;用于存储对象实例。一般通过new关键字创建的对象都存放在堆中&#xff0c;堆的大小可以通过启动参数…