(delphi11最新学习资料) Object Pascal 学习笔记---第10章第3节(事件驱动编程)

10.3 事件驱动编程

​ 在基于组件的程序库中(在许多其他情况下也是如此),您编写的代码不仅仅是一连串平顺的动作序列,而主要是反应的集合。这意味着你应该定义应用程序在发生某些事情时做出“反应”。这里“某些事情”可以是用户操作,例如单击按钮,系统操作,传感器状态的变化,通过远程连接获得的一些数据,或者几乎任何其他事情。

​ 这些外部或内部触发的行动通常称为事件。事件最初是对基于消息的操作系统的映射,如Windows,但从最初的概念到现在已经经历了很长的发展。事实上,在现代程序库中,大多数事件都是在设置属性、调用方法或与给定组件交互时(或间接与另一个组件)交互时触发。

​ 事件和事件驱动编程与 OOP 有什么关系?这两种方法在创建新继承类的时间和方式上与使用更一般的继承类不同。

​ 在纯正的面向对象编程中,每当一个对象具有不同于另一个对象的行为(或不同的方法)时,它应该属于不同的类。我们在几个演示中已经看到了这一点。

​ 让我们考虑以下情况:一个窗体有四个按钮。当你点击每个按钮时,它们需要不同的行为。因此,在纯OOP术语中,你应该有四个不同的按钮子类,每个子类都有一个不同的“click”方法。这种做法形式上是正确的,但需要编写和维护大量的额外代码,增加了复杂性。

​ 事件驱动编程考虑到了类似的情况,建议开发人员为同类按钮对象添加一些行为。这些行为将成为对象状态的装饰或扩展,而不需要一个新的类。 这种模式也被称为委托,因为对象的行为被委托给对象自身类以外的类的方法。

​ 不同的编程语言以不同的方式实现事件。例如:

  • 使用方法引用(在 Object Pascal 中称为方法指针)或使用内部方法引用事件对象(如在 C# 中);
  • 将事件代码委托给实现接口的专门类(如 Java 中的通常做法);
  • 使用闭包,如 JavaScript 中通常使用的方法(Object Pascal 也支持匿名方法,将在第 15 章中介绍)。然而,在JavaScript中,所有方法都是闭包,因此在这门语言中这两个概念之间的差异有点模糊。

​ 事件和事件驱动编程的概念已变得相当普遍,许多不同的编程语言和用户界面库都支持这一概念。然而,Delphi 实现支持事件的方式却非常独特。下面的内容将详细解释其背后的技术。

10.3.1 方法指针

​ 我们在第4章的最后一部分已经看到,Object Pascal语言有函数指针的概念。函数指针是一个存放函数内存位置的变量,可以用来间接调用函数。函数指针类型具有特定的签名(一组参数类型和一个返回类型,如果有的话)。

​ 同样,Object Pascal语言也有方法指针的概念。方法指针是对属于某个类的方法的内存位置的引用。与函数指针类型一样,方法指针类型也有特定的签名。然而,方法指针携带一些额外的信息,即:方法所属对象(换句话说,当调用该方法时将用作Self参数的对象)。

​ 换一种说法,方法指针是对内存中一个特定对象(特定实例,其数据位于特定内存位置)的方法(位于特定内存地址,为给定类的所有对象共享)的引用。为方法指针赋值时,必须引用给定对象的方法,即特定实例的方法!

注意 在底层使用TMethod表示这个概念,如果你查看这个数据结构的定义,你就能够更好的理解方法指针的实现。TMethod记录有两个域,Code和Data,分别表示方法的地址以及方法所属的对象。在其他类似的语言中,代码引用由委托类(C#)或接口方法(Java)捕获。

​ 方法指针类型的声明与过程类型指针的声明相似,不同之处在于在方法指针声明的末尾有of object 关键字:

typeTIntProceduralType = procedure(Num: Integer);TStringEventType = procedure(const S: string) of object;

​ 当你声明了一个方法指针类型(如上文所示)后,你就可以声明一个这种类型的变量,并将任何一个对象的兼容方法赋值给它。什么是兼容方法呢?就是与方法指针类型所要求的参数相同的方法,例如上例中的单字符串参数方法。只要与方法指针类型兼容,任何对象的方法引用都可以赋值给方法指针。

​ 既然已经有了方法指针类型,就可以声明一个这种类型的变量,并为其赋值一个兼容的方法:

typeTEventTest = classpublicprocedure ShowValue(const S: string);procedure UseMethod;end;procedure TEventTest.ShowValue(const S: string);
beginShow(S);
end;procedure TEventTest.UseMethod;
varStringEvent: TStringEventType;
beginStringEvent := ShowValue;StringEvent('Hello');
end;

​ 目前,这段简单的代码并没有真正解释事件的用处,因为它侧重于底层方法指针类型的概念。事件就是基于这种技术实现的、但又超越了这一概念,它将方法指针存储在一个对象(如按钮)中,从而引用另一个对象(如为按钮提供事件处理器的窗体中)的方法。在大多数情况下,事件也是通过属性实现的。

注意 尽管不太常用,您也可以使用匿名方法定义事件处理器。不太常用的原因是这个功能刚引入不久,那时已经有很多库存在了。此外,你能在第15章中学习到使用匿名方法的例子。另一种可能的扩展是为单个事件定义多个事件处理器,就像C#语言中支持的那样,这不是一个标准的功能,但是你可以自己实现。

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

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

相关文章

《ESP8266通信指南》7-Arduino 开发8266的环境配置与示例代码烧录

往期 《ESP8266通信指南》6-创建TCP服务器(AT指令)-CSDN博客 《ESP8266通信指南》5-TCP通信透传模式(AT指令)-CSDN博客 《ESP8266通信指南》4-以Client进行TCP通信(AT指令)-CSDN博客 《ESP8266通信指南》3-常用AT指令详解-826…

junit组件的使用

JUnit 是一个广泛使用的 Java 单元测试框架,它帮助开发者编写可重复运行的测试用例来验证代码的正确性。下面是使用 JUnit 进行单元测试的基本步骤和一些关键概念: 安装与配置 依赖管理:如果你使用的是 Maven 或 Gradle 等构建工具&#xff…

OneFlow概念清单

OneFlow概念清单 摘要: OneFlow是一个开源的深度学习框架,旨在为科研人员和开发者提供一个易于使用、高效且灵活的平台。本文将详细介绍OneFlow的核心概念,包括其架构、特性以及在深度学习领域的应用。通过阅读本文,读者将能够全…

elasticsearch 常用语法汇总

文章目录 前言elasticsearch 常用语法汇总1. 创建索引2. 检索索引信息3. 删除索引4. 文档操作4.1. 对blog_new索引指定文档ID新增4.2. 对blog_new索引不指定文档ID新增,随机文档ID:4.3. 获取文档4.4. 更新文档4.5. 删除文档 5. 查询5.1. 匹配查询5.2. 范围查询5.3. …

HackMyVM-Vulny

目录 信息收集 arp nmap nikto WEB信息收集 主页信息收集 gobuster RCE漏洞 反弹shell 提权 系统信息收集 横向渗透 flock提权 信息收集 arp ┌──(root㉿0x00)-[~/HackMyVM] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC…

从NuGet获取OpenTK

OpenTK是一个开源、跨平台的游戏开发库,由MonoGame团队创建。它为C#开发者提供了一个简单易用的接口,以便使用OpenGL、OpenAL和OpenCL进行3D渲染、音频处理和并行计算。OpenTK的目标是提供一个一致且高效的框架,让开发者能够专注于构建他们的…

鸿蒙(HarmonyOS)性能优化实战-Trace使用教程

概述 OpenHarmony的DFX子系统提供了为应用框架以及系统底座核心模块的性能打点能力,每一处打点即是一个Trace,其上附带了记录执行时间、运行时格式化数据、进程或线程信息等。开发者可以使用SmartPerf-Host调试工具对Trace进行解析,在其绘制…

arcgis js 4.x加载SceneLayer并实现基于属性查询定位及高亮

一、代码 <!DOCTYPE html> <html> <head><meta charset"utf-8" /><meta name"viewport" content"widthdevice-width, initial-scale1,maximum-scale1,user-scalableno"><title></title><link rel…

python批量删除文件

python批量删除文件 1、查询与删除2、添加模块到地址中3、批量删除多个路径中不需要导出的文件 1、查询与删除 mport osdef get_files_in_folder(folder_path):files []for file in os.listdir(folder_path):if os.path.isfile(os.path.join(folder_path, file)):files.appen…

微信小程序:5.数据绑定

在Data中定义数据早wxml中进行数据使用 在data中定义数据 在页面对应的js对象中找到data&#xff0c;然后把数据进行定义即可 Page({data: {motto: Hello World,userInfo: {avatarUrl: defaultAvatarUrl,nickName: ,},hasUserInfo: false,canIUseGetUserProfile: wx.canIUse…

关于OSPF报文学习

目录 一.OSPF学习补充 &#xff08;1&#xff09;OSPF报文头部 &#xff08;2&#xff09;ospf建立邻居关系 1.Hello报文——建立邻居关系 2.hello报文头部 &#xff08;3&#xff09;OSPF建立邻接关系 1.发送DD报文 2.DD报文头部 &#xff08;4&#xff09;关于DR,BD…

力扣经典150题第四十三题:两数之和

目录 力扣经典150题第四十三题&#xff1a;两数之和题目描述示例解题思路完整代码复杂度分析总结与结语感谢您阅读本文&#xff0c;希望本文能帮助您更好地理解和掌握解决这道经典的算法问题&#xff01; 力扣经典150题第四十三题&#xff1a;两数之和 题目描述 给定一个整数…

pyqt QSplitter控件

pyqt QSplitter控件 QSplitter控件效果代码 QSplitter控件 PyQt中的QSplitter控件是一个强大的布局管理器&#xff0c;它允许用户通过拖动边界来动态调整子控件的大小。这个控件对于创建灵活的、用户可定制的用户界面非常有用。 QSplitter控件可以水平或垂直地分割其包含的子…

Bytebase 2.16.0 - 支持 Oracle 和 SQL Server DML 变更的事前备份

&#x1f680; 新功能 支持 Oracle 和 SQL Server DML 变更的事前备份。 支持在 SQL 编辑器中显示存储过程和函数。 支持兼容 TDSQL 的 MySQL 和 PostgreSQL 版本。 支持把数据库密码存储在 AWS Secrets Manager 和 GCP Secret Manager。 支持通过 IAM 连接到 Google Clou…

目标检测与追踪AI算法模型及边缘计算智能分析网关V4的算法应用

目标检测与追踪是计算机视觉领域中的一个重要任务&#xff0c;主要用于识别图像或视频中的目标&#xff0c;并跟踪它们的运动轨迹。针对这一任务&#xff0c;有许多先进的AI算法模型&#xff0c;例如&#xff1a; YOLO&#xff08;You Only Look Once&#xff09;&#xff1a;…

分布式版本控制系统——Git

分布式版本控制系统——Git 一、Git安装二、创建版本库三、将文件交给Git管理四、Git的工作区和暂存区1.工作区&#xff08;Working Directory&#xff09;2.版本库 五、版本回退和撤销修改1.版本回退2.撤销修改 六、删除文件七、常用基础命令总结八、参考 分布式版本控制系统&…

Qt应用程序直接在没有环境的windows系统电脑上运行

参考&#xff1a;QT 发布应用程序 在没有安装QT的电脑上运行程序 文章目录 创建一个空的文件夹test将可执行程序exe拷贝到test打开对应qt命令行输入 windeployqt e:\test\exename.exe 创建一个空的文件夹test 将可执行程序exe拷贝到test 打开对应qt命令行 输入 windeployqt e:…

【Flutter 面试题】 怎么减少Widget的重新构建?

【Flutter 面试题】 怎么减少Widget的重新构建? 文章目录 写在前面口述回答补充说明示例代码解释运行结果写在前面 🙋 关于我 ,小雨青年 👉 CSDN博客专家,GitChat专栏作者,阿里云社区专家博主,51CTO专家博主。2023博客之星TOP153。 👏🏻 正在学 Flutter 的同学,…

Swift字符串

在 Swift 中&#xff0c;Character 和 String 是用于处理文本数据的两个重要类型。 Character Character 是 Swift 中用于表示单个 Unicode 字符的类型。每个 Character 实例都代表一个可见的字符&#xff08;如字母、数字、标点符号等&#xff09;&#xff0c;或者一个不可见的…