(delphi11最新学习资料) Object Pascal 学习笔记---第14章泛型第3节(特定类约束)
14.3.2 特定类约束
如果您的泛型类需要使用某个特定子集的类(特定层次结构),则可能需要根据给定基类指定约束。
例如,如果您声明:
typeTCompClass<T: TComponent> = class
则此泛型类的实例仅适用于组件类,即任何TComponent后代类。这使您拥有一个非常特定的泛型类型(是的,听起来很奇怪,但这确实是它的实际情况),并且编译器将允许您在处理泛型类型时使用TComponent类的所有方法。
如果这看起来非常强大,那么请三思。如果你考虑一下利用继承和类型兼容规则可以实现的功能,也许你可以使用传统的面向对象技术来解决同样的问题,而不必使用泛型类。我并不是说特定的类约束从来都没有用,但它肯定没有更高级别的类约束或(我觉得非常有趣的)基于接口的约束强大。
14.3.3 接口约束
一般来说,更灵活的做法是只接受实现特定接口的类作为类型参数,而不是将一个泛型类约束为一个给定的类。这样就可以在泛型的实例上调用接口。在 C# 语言中,将接口约束用于泛型也很常见。让我先展示给你一个示例(来自IntfConstraint示例)。首先,我们需要声明一个接口:
typeIGetValue = interface['{60700EC4-2CDA-4CD1-A1A2-07973D9D2444}']function GetValue: Integer;procedure SetValue(Value: Integer);property Value: Integer read GetValue write SetValue;end;
接下来,我们可以定义一个实现它的类:
typeTGetValue = class(TNoRefCountObject, IGetValue)privateFValue: Integer;publicconstructor Create(Value: Integer = 0);function GetValue: Integer;procedure SetValue(Value: Integer);end;
在限制为实现特定接口的类型的泛型类的定义中,事情开始变得有趣:
typeTInftClass<T: IGetValue> = classprivateFVal1, FVal2: T; // Or IGetValuepublicprocedure Set1(Val: T);procedure Set2(Val: T);function GetMin: Integer;function GetAverage: Integer;procedure IncreaseByTen;end;
请注意,在这个类的泛型方法的代码中,我们可以编写:
function TInftClass<T>.GetMin: Integer;
beginResult := Min(FVal1.GetValue, FVal2.GetValue);
end;procedure TInftClass<T>.IncreaseByTen;
beginFVal1.SetValue(FVal1.GetValue + 10);FVal2.Value := FVal2.Value + 10;
end;
有了所有这些定义,我们现在可以按以下方式使用泛型类:
procedure TFormIntfConstraint.BtnValueClick(Sender: TObject);
varIClass: TInftClass<TGetValue>;
beginIClass := TInftClass<TGetValue>.Create;tryIClass.Set1(TGetValue.Create(5));IClass.Set2(TGetValue.Create(25));Show('Average: ' + IntToStr(IClass.GetAverage));IClass.IncreaseByTen;Show('Min: ' + IntToStr(IClass.GetMin));finallyIClass.FVal1.Free;IClass.FVal2.Free;IClass.Free;end;
end;
为了展示这个泛型类的灵活性,我为接口创建了另一个完全不同的实现方法:
type
TButtonValue = class(TButton, IGetValue)
publicfunction GetValue: Integer;procedure SetValue(Value: Integer);class function MakeTButtonValue(Owner: TComponent; Parent: TWinControl): TButtonValue;
end;function TButtonValue.GetValue: Integer;
beginResult := Left; // use base class property
end;procedure TButtonValue.SetValue(Value: Integer);
beginLeft := Value; // use base class property
end;
该类函数(此处未显示)在父控件中创建了一个随机位置的按钮。位置创建一个按钮,并在以下示例代码中使用:
procedure TFormIntfConstraint.BtnValueButtonClick(Sender: TObject);
varIClass: TInftClass<TButtonValue>;
beginIClass := TInftClass<TButtonValue>.Create;tryIClass.Set1(TButtonValue.MakeTButtonValue(Self, ScrollBox1));IClass.Set2(TButtonValue.MakeTButtonValue(Self, ScrollBox1));Show('Average: ' + IntToStr(IClass.GetAverage));Show('Min: ' + IntToStr(IClass.GetMin));IClass.IncreaseByTen;Show('New Average: ' + IntToStr(IClass.GetAverage));finallyIClass.Free;end;
end;
相关文章:
(delphi11最新学习资料) Object Pascal 学习笔记---第14章泛型第3节(特定类约束)
14.3.2 特定类约束 如果您的泛型类需要使用某个特定子集的类(特定层次结构),则可能需要根据给定基类指定约束。 例如,如果您声明: typeTCompClass<T: TComponent> class 则此泛型类的实例仅适用于组…...
【postgresql初级使用】视图上的触发器instead of,替代计划的rewrite,实现不一样的审计日志
instead of 触发器 专栏内容: postgresql使用入门基础手写数据库toadb并发编程 个人主页:我的主页 管理社区:开源数据库 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物. 文章目录 inst…...
window.setInterval(func,interval)定时器
window.setInterval()是JavaScript中的方法,用于在指定的时间间隔重复执行某个函数或代码块。它接受两个参数,第一个参数是要执行的函数或代码块,第二个参数是时间间隔(以毫秒为单位)。 以下是使用window.setInterval…...
Einstein Summation 爱因斯坦求和 torch.einsum
Einstein Summation 爱因斯坦求和 torch.einsum flyfish 理解爱因斯坦求和的基本概念和语法,这对初学者来说可能有一定难度。对于不熟悉该表示法的用户来说,可能不如直接的矩阵乘法表达式易于理解。 整个思路是 向量的点积 -》矩阵乘法-》einsum 向…...
TCP攻击是怎么实现的,如何防御?
TCP(Transmission Control Protocol)是互联网协议族中的重要组成部分,用于在不可靠的网络上提供可靠的数据传输服务。然而,TCP协议的一些特性也使其成为攻击者的目标,尤其是DDoS(Distributed Denial of Ser…...
Chrome DevTools开发者调试工具
Chrome DevTools 是一个功能强大的网页开发工具,集成在谷歌浏览器中,帮助开发者调试和优化网页应用。以下是详细的功能说明和使用技巧: 1. 打开 DevTools 快捷键:按下 F12 或 CtrlShiftI(Windows/Linux)或…...
产品创新管理:从模仿到引领,中国企业的创新之路
一、引言 在全球化竞争日益激烈的今天,科技创新已成为推动国家经济增长和社会进步的关键动力。中国自改革开放四十年来,在科技创新领域取得了举世瞩目的成就,从跟踪模仿到自主研发,再到自主创新、开放创新和协同创新并举…...
Android 日志实时输出
开发中如果只是单纯的应用开发,Android studio基本上可以满足,但是如果应用和系统联调那就得用logcat实时输出了,我这里都是总结的实用经验,没那么多花里胡哨 Android 日志实时输出 1、输出 android log //分步,进入s…...
JavaEE初阶---多线程编程(一.线程与进程)
目录 🤣一.线程与进程的概念与联系: 进程的基本概念: 线程的基本概念: 进程和线程的区别与联系: 🙃代码执行实列: 1.通过继承Thread父类来实现多线程 2.通过实现Runnable接口来实现多线程…...
react+vite创建
要在本地初始化一个结合了React和Vite的项目,你可以遵循以下步骤: 1、安装Node.js: 确保你的机器上已安装了Node.js。如果未安装,请前往Node.js官网下载并安装。 2、使用终端或命令提示符: 打开你的终端(…...
软考 系统架构设计师系列知识点之杂项集萃(29)
接前一篇文章:软考 系统架构设计师系列知识点之杂项集萃(28) 第46题 以下描述中,( )不是嵌入式操作系统的特点。 A. 面向应用,可以进行裁剪和移植 B. 用于特定领域,不需要支持多任…...
[Qt开发]当我们在开发兼容高分辨率和高缩放比、高DPI屏幕的软件时,我们在谈论什么。
前言 最近在开发有关高分辨率屏幕的软件,还是做了不少尝试的,当然我们也去网上查了不少资料,但是网上的资料也很零碎,说不明白,这样的话我就做个简单的总结,希望看到这的你可以一次解决你有关不同分辨率下…...
uniapp视频组件层级太高,解决方法使用subNvue原生子体窗口
目录 前言 先看一下uniapp官网的原话: subNvue的一些参数介绍 subNvues使用方法: 绑定id 显示 subNvue 弹出层 subNvue.show() 参数信息 subNvue.hide() 参数信息 在使用subNvue 原生子体窗口 遇到的一些问题 前言 nvue 兼容性 以及使用方式 控…...
java项目使用jsch下载ftp文件
pom <dependency><groupId>com.jcraft</groupId><artifactId>jsch</artifactId><version>0.1.55</version> </dependency>demo1:main方法直接下载 package com.example.controller;import com.jcraft.jsch.*; im…...
指针(初阶1)
一.指针是什么 通俗的讲,指针就是地址,其存在的意义就像宾馆房间的序号一样是为了更好的管理空间。 如下图: 如上图所示,指针就是指向内存中的一块空间,也就相当于地址 二.一个指针的大小是多少 之前我们学习过&#x…...
MySQL实体类框架
实现mysql数据库的增删改查功能 import com.mchange.v2.collection.MapEntry; import lombok.Data; import org.junit.jupiter.api.Test;import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.*; import java.sql.*; …...
数据结构之初始泛型
找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程(ಥ_ಥ)-CSDN博客 所属专栏:数据结构(Java版) 目录 深入了解包装类 包装类的由来 装箱与拆箱 面试题 泛型 泛型的语法与使用…...
【网络编程开发】7.TCP可靠传输的原理
7.TCP可靠传输的原理 TCP实现可靠传输的原理主要基于序列号和确认应答、超时重传、滑动窗口、连接管理机制以及拥塞控制等多重机制。 TCP(Transmission Control Protocol),即传输控制协议,是网络通信中的一种重要协议࿰…...
视觉SLAM十四讲:从理论到实践(Chapter8:视觉里程计2)
前言 学习笔记,仅供学习,不做商用,如有侵权,联系我删除即可 一、目标 1.理解光流法跟踪特征点的原理。 2.理解直接法是如何估计相机位姿的。 3.实现多层直接法的计算。 特征点法存在缺陷: 二、光流(Optical Flow) …...
C语言过度C++语法补充(面向对象之前语法)
目录 1. C相较于C语言新增的语法 0. C 中的输入输出 1. 命名空间 1. 我们如何定义一个命名空间? 2. 如何使用一个命名空间 3. 命名空间中可以定义什么? 4. 在 相同或者不同 的文件中如果出现 同名的命名空间 会如何? 5. 总结~~撒花~~…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
学习一下用鸿蒙DevEco Studio HarmonyOS5实现百度地图
在鸿蒙(HarmonyOS5)中集成百度地图,可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API,可以构建跨设备的定位、导航和地图展示功能。 1. 鸿蒙环境准备 开发工具:下载安装 De…...
Ubuntu系统多网卡多相机IP设置方法
目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机,交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息,系统版本:Ubuntu22.04.5 LTS;内核版本…...
AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
ubuntu中安装conda的后遗症
缘由: 在编译rk3588的sdk时,遇到编译buildroot失败,提示如下: 提示缺失expect,但是实测相关工具是在的,如下显示: 然后查找借助各个ai工具,重新安装相关的工具,依然无解。 解决&am…...
react菜单,动态绑定点击事件,菜单分离出去单独的js文件,Ant框架
1、菜单文件treeTop.js // 顶部菜单 import { AppstoreOutlined, SettingOutlined } from ant-design/icons; // 定义菜单项数据 const treeTop [{label: Docker管理,key: 1,icon: <AppstoreOutlined />,url:"/docker/index"},{label: 权限管理,key: 2,icon:…...
