类和记录的 helpers(助手)

  • 前言
  • 一、关于类和记录的 helpers(助手)
  • 二、helpers(助手)语法定义
  • 三、定义Helpers(助手)
  • 总结
  • 附: helpers(助手)实际应用
    • A、Delphi原生的JSON操作助手实现
      • TJSONObject 的Helper 单元:
      • 使用样例:

前言

Delphi 从XE版本开始提供类和记录的 Helper(助手) 封装,这样就可以很方便的在不修改原来类或者记录的原始定义情况下,给类和记录增加新的功能。 本文简要介绍 Helper 的实现,最后实际举例实现了TJSONObject的Helper,让使用delphi原生的JSON对象也能像SuperObject一样书写方式操作。


一、关于类和记录的 helpers(助手)

Helpers(助手)是一种不使用继承的方法来扩充类或者记录的功能,对于记录类型更是有用,因为类可以通过继承来增加功能二记录不可以继承。适用于一些没有源代码或者源代码不适合进行变更的类的扩展。对于自己原始设计的程序,不应该使用这种类的扩展方法,应该始终依赖于普通的类继承和接口实现。

二、helpers(助手)语法定义

typeidentifierName = class|record helper [(ancestor list)] for TypeIdentifierNamememberListend;

ancestor list 是可选的,而且只能适用于类Helpers;助手类型不能声明实例数据,但允许使用类字段(class fields);其他可见性范围规则和成员列表语法与普通类和记录类型相同。

例如:

typeTJSONObjectHelper = class helper for TJSONObject

注意:类和记录Helpers不支持运算符重载。
可以定义多个辅助helpers(助手)并将其与单个类型关联。但是,只有零个或一个helpers(助手)起作用,这决定于助手定义的单元引入的位置。类或记录助手作用域是以正常的Delphi方式确定的(例如,在单元的uses子句中从右到左)。

三、定义Helpers(助手)

下面的代码演示类助手的声明(记录助手的行为方式相同):

typeTMyClass = classprocedure MyProc;function  MyFunc: Integer;end;...procedure TMyClass.MyProc;var X: Integer;beginX := MyFunc;end;function TMyClass.MyFunc: Integer;begin...end;...typeTMyClassHelper = class helper for TMyClassprocedure HelloWorld;function MyFunc: Integer;end;...procedure TMyClassHelper.HelloWorld;beginWriteln(Self.ClassName); // Self refers to TMyClass type, not TMyClassHelperend;function TMyClassHelper.MyFunc: Integer;begin...end;...varX: TMyClass;beginX := TMyClass.Create;X.MyProc;    // 调用 TMyClass.MyProcX.HelloWorld; // 调用 TMyClassHelper.HelloWorldX.MyFunc;    // 调用 TMyClassHelper.MyFunc

提示:请记住,调用类助手函数MyFunc是因为类助手优先于实际的类类型。

总结

1. Helpers语法定义:TJSONObjectHelper = class helper for TJSONObject

2.定义好Helper单元后,需要在使用的单元中引用,Helper(助手)才会起作用;

3.Helper是一种类的扩展方法,但不是设计时使用的方法,原始设计应该始终依赖于普通的类继承和接口实现。

附: helpers(助手)实际应用

A、Delphi原生的JSON操作助手实现

使用Delphi的朋友都知道,三方JSON处理单元SuperObject.pas非常有名气,特别是操作JSON对象的方法非常简单。例如:jo.S[‘Name’] := ‘sensor’,或者 i := jo.I[‘age’],非常方便。但是delphi原生的操作起来,代码就多很多,例如:jo.TryGetValue(‘Name’,js),才能取出值,书写的代码比较多,繁琐,那么通过给TJSONObject 增加一个Helper(助手)就可以实现和SuperObject一样的操作方法。

S[]:表示字符串
I[]:表示整型数
I64[]:表示int63
D[]:表示日期
A[]:表示数组
O[]:表示TJSONObject对象
B[]:表示逻辑值

TJSONObject 的Helper 单元:
{**************************************
时间:2021-06-18
功能:1 实现delphi原生的JSON操作为 S[] 操作方式
作者:sensor
}
unit uSZHN_JSON;interface
uses//System.Classes,//System.Types,//System.DateUtil,//System.Generics.Collections,//System.SysUtils,System.JSON;typeTJSONObjectHelper = class helper for TJSONObjectprivatefunction  Get_ValueS(PairName : string) : string;procedure Set_ValueS(PairName,PairValue : string);function  Get_ValueI(PairName : string) : Integer;procedure Set_ValueI(PairName : string; PairValue : Integer);function  Get_ValueI64(PairName : string) : Int64;procedure Set_ValueI64(PairName : string; PairValue : Int64);function  Get_ValueD(PairName : string) : TDateTime;procedure Set_ValueD(PairName : string; PairValue : TDateTime);function  Get_ValueB(PairName : string) : Boolean;procedure Set_ValueB(PairName : string; PairValue : Boolean);function  Get_ValueA(PairName : string) : TJSONArray;procedure Set_ValueA(PairName : string; PairValue : TJSONArray);function  Get_ValueO(PairName : string) : TJSONObject;procedure Set_ValueO(PairName : string; PairValue : TJSONObject);public//判断某个字段是否存在function PairExists(PairName : string) : Boolean;//定义字段读取函数property S[PairName : string] : string      read Get_ValueS   write Set_ValueS;property I[PairName : string] : integer     read Get_ValueI   write Set_ValueI;property I64[PairName : string] : Int64     read Get_ValueI64 write Set_ValueI64;property D[PairName : string] : TDateTime   read Get_ValueD   write Set_ValueD;property B[PairName : string] : Boolean     read Get_ValueB   write Set_ValueB;property A[PairName : string] : TJSONArray  read Get_ValueA   write Set_ValueA;property O[PairName : string] : TJSONObject read Get_ValueO   write Set_ValueO;end;implementation{ TJSONObjectHelper }function TJSONObjectHelper.Get_ValueS(PairName: string): string;
varjs : TJSONString;
beginif PairName = '' then  Exit;if Self.TryGetValue(PairName,js) thenResult := js.ValueelseResult := '';
end;function TJSONObjectHelper.PairExists(PairName: string): Boolean;
beginResult := Self.Values[PairName] <> nil;
end;procedure TJSONObjectHelper.Set_ValueS(PairName, PairValue: string);
varjs : TJSONString;
begin//1. 首先查找有没有该字段, 如果有,则直接删除if Self.TryGetValue(PairName,js) thenbeginSelf.RemovePair(PairName).Free; //如果没有free,就会产生内存泄露end;//2. 然后在增加Self.AddPair(PairName, PairValue);
end;function TJSONObjectHelper.Get_ValueI(PairName: string): Integer;
varji : TJSONNumber;
beginif PairName = '' then  Exit(0);if Self.TryGetValue(PairName,ji) thenResult := ji.AsIntelseResult := 0;
end;procedure TJSONObjectHelper.Set_ValueI(PairName: string; PairValue: Integer);
varjn : TJSONNumber;
begin//1. 首先查找有没有该字段, 如果有,则直接删除if Self.TryGetValue(PairName,jn) thenSelf.RemovePair(PairName).Free;//2. 然后在增加Self.AddPair(PairName, TJSONNumber.Create(PairValue));
end;function TJSONObjectHelper.Get_ValueD(PairName: string): TDateTime;
varji : TJSONNumber;
beginif PairName = '' then  Exit(0);if Self.TryGetValue(PairName,ji) thenResult := ji.AsDoubleelseResult := 0;
end;procedure TJSONObjectHelper.Set_ValueD(PairName: string; PairValue: TDateTime);
varjn : TJSONNumber;
begin//1. 首先查找有没有该字段, 如果有,则直接删除if Self.TryGetValue(PairName,jn) thenSelf.RemovePair(PairName).Free;Self.AddPair(PairName, TJSONNumber.Create(PairValue));
end;function TJSONObjectHelper.Get_ValueB(PairName: string): Boolean;
varjb : TJSONBool;
beginif PairName = '' then  Exit(False);if Self.TryGetValue(PairName,jb) thenResult := jb.AsBooleanelseResult := False;
end;procedure TJSONObjectHelper.Set_ValueB(PairName: string; PairValue: Boolean);
varjb : TJSONBool;
begin//1. 首先查找有没有该字段, 如果有,则直接删除if Self.TryGetValue(PairName,jb) thenSelf.RemovePair(PairName).Free;Self.AddPair(PairName, TJSONBool.Create(PairValue));
end;function TJSONObjectHelper.Get_ValueI64(PairName: string): Int64;
varji : TJSONNumber;
beginif PairName = '' then  Exit(0);if Self.TryGetValue(PairName,ji) thenResult := ji.AsInt64elseResult := 0;
end;procedure TJSONObjectHelper.Set_ValueI64(PairName: string; PairValue: Int64);
varjn : TJSONNumber;
begin//1. 首先查找有没有该字段, 如果有,则直接删除if Self.TryGetValue(PairName,jn) thenSelf.RemovePair(PairName).Free;Self.AddPair(PairName, TJSONNumber.Create(PairValue));
end;function TJSONObjectHelper.Get_ValueA(PairName: string): TJSONArray;
varja : TJSONArray;
beginif PairName = '' then  Exit(nil);Self.TryGetValue(PairName,Result);
end;procedure TJSONObjectHelper.Set_ValueA(PairName: string; PairValue: TJSONArray);
varja : TJSONArray;
begin//1. 首先查找有没有该字段, 如果有,则直接删除if Self.TryGetValue(PairName,ja) thenSelf.RemovePair(PairName).Free;Self.AddPair(PairName, PairValue);
end;function TJSONObjectHelper.Get_ValueO(PairName: string): TJSONObject;
varjo : TJSONObject;
beginif PairName = '' then  Exit(nil);if Self.TryGetValue(PairName,jo) thenResult := joelseResult := nil;
end;procedure TJSONObjectHelper.Set_ValueO(PairName: string; PairValue: TJSONObject);
varjo : TJSONObject;
begin//1. 首先查找有没有该字段, 如果有,则直接删除if Self.TryGetValue(PairName,jo) thenSelf.RemovePair(PairName).Free;Self.AddPair(PairName, PairValue as TJSONObject);
end;end.
使用样例:
uses.....uSZHN_JSON;function TForm1.Create_JSON: string;
varjo,jo1 : TJSONObject;ja : TJSONArray;beginjo  := TJSONObject.Create;jo1  := TJSONObject.Create;//ja := TJSONArray.Create;tryjo.S['Name'] := 'sensor';jo.S['Name'] := 'sensor11';   //重复字段,内容以最后一个为准jo.I['age']  := 54;jo.I['age']  := 64;  //按照最后一个jo.D['birth'] := now;jo.B['worked']:= True;jo.I64['money'] := $7FF1F2F3F4F5F6F7;  //大数据jo.O['OBJ'] := TJSONObject.Create;jo.O['OBJ'].S['AAAA'] := '1200';jo.O['jjoo11'] := jo1;jo1.AddPair('ABC','ABC1000');jo.a['ArrayDemo'] := TJSONArray.Create;;jo.a['ArrayDemo'].Add('中国');jo.a['ArrayDemo'].Add(100);jo.a['ArrayDemo'].Add('wwww');jo.a['ArrayDemo'].Add(true);Result := jo.ToString;finallyjo.Free;  //释放只需要释放jo就可以,其他的会自动释放(包括jo1)end;
end;

看完本片文章后,你能否实现将TFDQuery也Helper,让其操作也能使用S[]模式,而不在是FieldByName的模式!减少代码编写量!

【delphi】类和记录的 helpers(助手)相关推荐

  1. delphi 类的写法 和 控制台程序的制作---深入Delphi编程

    刚刚接触的Delphi的朋友,可能最感兴趣的就是它丰富.强大的VCL(可视化构件库).仅仅向窗体上扔几个构件,甚至不用动手写代码,就能很容易地做出一个有实用价值的程序,真是令人激动.但是,VCL只是D ...

  2. yii2 html帮助类,Yii2 学习笔记之助手类(HelperClass)

    一.数组助手类 // 常用的就是建立哈希表,map()方法.一般在使用dropDownList的时候, // 会从查询出来的对象列表中获取到这样的$array供其使用. // 参考http://www ...

  3. delphi 以前的记录,调试,代码,记录,排错等

    经常看到一些程序里面用到如: {$ifdef win16},{$ifdef win32}之类的信息, 可是这些好像并没有定义,不知道在哪里可以找到这些条件编译的定义或者是说明具体讲述win16代表什么 ...

  4. 微信小程序云开发日记类日记记录分享动态

    微信公众号:创享日记(微信号csds992022) 发送关键词:日记类小程序 免费获取源码 1 概述 1.1 关于本手册 为了使您对研岸日记记录社交软件的使用有清晰详尽的了解,特此编写<用户手册 ...

  5. delphi类没有注册

    使用modi ,结果delphi7,delphi2006,delphixe3都出现类没有注册. 跟踪发现对象创建了.dll模块也确实加载了. 一到create vb6很正常.vc6也正常. 有人说是因 ...

  6. Delphi中准确记录程序执行时间

    知道如何在你的Windows和跨平台应用程序中获得一个操作的确切执行时间的信息,在各种情况下都是有用的.例如,当你需要向用户展示一个长的操作的执行时间时,它可能是必要的(顺便说一下,在这种情况下,很少 ...

  7. delphi 类class自定义类方法虚方法

    刚刚接触的Delphi的朋友,可能最感兴趣的就是它丰富.强大的VCL(可视化构件库).仅仅向窗体上扔几个构件,甚至不用动手写代码,就能很容 易地做出一个有实用价值的程序,真是令人激动.但是,VCL只是 ...

  8. String类常用方法记录

    String类常用方法练习 package cn.zixi;import java.nio.charset.StandardCharsets; import java.util.Arrays; imp ...

  9. 重新组织数据之十二 :Replace Record with Data Class(以数据类取代记录)

    你需要面对传统编程环境中的record structure  (记录结构). 为该record (记录)创建一个「咂」数据对象(dumb data object). 动机(Motivation) Re ...

最新文章

  1. 微信小程序之购物车功能
  2. 【BZOJ】3771: Triple FTT+生成函数
  3. [html] marquee详解
  4. Python教程:多维列表(元组)碾成一维形式
  5. OpenGL Texture Wrap Modes纹理包裹模式的实例
  6. 【鬼网络】之NFS共享服务
  7. springboot 页面下载文件 网页下载文件功能 文件放resourcce下面
  8. python我想对你说_python学习第3天-----字典、解构
  9. oracle 10g 学习之函数和存储过程(12)
  10. SpringBoot防XSS攻击
  11. 用python做逻辑回归_python实现逻辑回归
  12. maven工程找不到jar包(依赖)的解决方法
  13. 【numpy学习】numpy教程--基于莫烦python的教程
  14. delphi完美经典--第十八章
  15. Outlook_Hotkey
  16. 聊聊旷厂黑科技 | 手机多摄的终极奥义是“多”吗?
  17. apollo星火计划课堂笔记---(综述、V2X、Routing、Map、Planning)
  18. 如何使用python读取modbus/TCP协议数据
  19. 深夜切题——Doubles
  20. 使用handeye_calib_camodocal进行手眼标定

热门文章

  1. RISC和CISC、统一编址和独立编址、冯诺依曼结构和哈佛结构
  2. 统一编址独立编址哈佛结构冯诺依曼结构
  3. 大话西游精彩对白(双语版2)
  4. FFmpeg 中的 log 输出到 Android 的 logcat 中
  5. 选中一行或多行的快捷键
  6. 在Unity中构建Pong克隆:UI和游戏玩法
  7. linux查看已杀死的进程,linux 查看并杀死僵尸进程
  8. 查看nginx版本号的几种方法
  9. [附源码]SSM计算机毕业设计闲置物品交易管理系统JAVA
  10. python练习题——我要买票吗