在今后的 Delphi 中, 以接口、结构为主的设计应该会越来越多, 因为这样太方便了.
System.RegularExpressions 就是以结构为主体设计的非常好的示范; 但更多东西使用接口会更合适.
有见过他人早就使用接口写程序, 从手头的这个程序开始我才开始使用.
现在基本总结出四种框架模式: 1、直接实现; 2、间接实现(或叫继承实现); 3、覆盖实现; 4、委托实现.
一、直接实现:
下例中虽有 TMy1、TMy2, 但在具体应用中使用的应是 IMy1、IMy2, 这就是我所谓的以接口为主导.
TMy1、TMy2 直接实现了所属接口的所有方法, 这是我所谓的直接实现.
这样可能会有代码重复, 但如果程序很小, 还是挺实用的.
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs; type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); end; IA = Interface procedure Method_A; end; IB = Interface(IA) procedure Method_B; end; IMy1 = Interface(IB) procedure Method_My1; end; IMy2 = Interface(IB) procedure Method_My2; end; TMy1 = class(TInterfacedObject, IMy1) procedure Method_A; procedure Method_B; procedure Method_My1; end; TMy2 = class(TInterfacedObject, IMy2) procedure Method_A; procedure Method_B; procedure Method_My2; end; var Form1: TForm1; implementation {$R *.dfm} { TMy1 } procedure TMy1.Method_A; begin ShowMessage('A'); end; procedure TMy1.Method_B; begin ShowMessage('B'); end; procedure TMy1.Method_My1; begin ShowMessage('My1'); end; { TMy2 } procedure TMy2.Method_A; begin ShowMessage('A'); end; procedure TMy2.Method_B; begin ShowMessage('B'); end; procedure TMy2.Method_My2; begin ShowMessage('My2'); end; {测试} procedure TForm1.FormCreate(Sender: TObject); var v1: IMy1; v2: IMy2; begin v1 := TMy1.Create; v1.Method_A; v1.Method_B; v1.Method_My1; v2 := TMy2.Create; v2.Method_A; v2.Method_B; v2.Method_My2; end; end.
二、间接实现:
下面例子通过一个间接的 TB 类, 避免了 TMy1、TMy2 中可能会重复的代码.
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs; type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); end; IA = Interface procedure Method_A; end; IB = Interface(IA) procedure Method_B; end; TB = class(TInterfacedObject, IB) procedure Method_A; procedure Method_B; end; IMy1 = Interface(IB) procedure Method_My1; end; IMy2 = Interface(IB) procedure Method_My2; end; TMy1 = class(TB, IMy1) procedure Method_My1; end; TMy2 = class(TB, IMy2) procedure Method_My2; end; var Form1: TForm1; implementation {$R *.dfm} { TB } procedure TB.Method_A; begin ShowMessage('A'); end; procedure TB.Method_B; begin ShowMessage('B'); end; { TMy1 } procedure TMy1.Method_My1; begin ShowMessage('My1'); end; { TMy2 } procedure TMy2.Method_My2; begin ShowMessage('My2'); end; {测试} procedure TForm1.FormCreate(Sender: TObject); var v1: IMy1; v2: IMy2; begin v1 := TMy1.Create; v1.Method_A; v1.Method_B; v1.Method_My1; v2 := TMy2.Create; v2.Method_A; v2.Method_B; v2.Method_My2; end; end.
三、覆盖实现:
从 TB 继承的过程中当然也可以通过覆盖虚函数而实现多态, 下面的 TMy2 就这么做了.
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs; type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); end; IA = Interface procedure Method_A; end; IB = Interface(IA) procedure Method_B; end; TB = class(TInterfacedObject, IB) procedure Method_A; virtual; procedure Method_B; virtual; end; IMy1 = Interface(IB) procedure Method_My1; end; IMy2 = Interface(IB) procedure Method_My2; end; TMy1 = class(TB, IMy1) procedure Method_My1; end; TMy2 = class(TB, IMy2) procedure Method_A; override; procedure Method_B; override; procedure Method_My2; end; var Form1: TForm1; implementation {$R *.dfm} { TB } procedure TB.Method_A; begin ShowMessage('A'); end; procedure TB.Method_B; begin ShowMessage('B'); end; { TMy1 } procedure TMy1.Method_My1; begin ShowMessage('My1'); end; { TMy2 } procedure TMy2.Method_A; begin ShowMessage('A_My2'); end; procedure TMy2.Method_B; begin ShowMessage('B_My2'); end; procedure TMy2.Method_My2; begin ShowMessage('My2'); end; {测试} procedure TForm1.FormCreate(Sender: TObject); var v1: IMy1; v2: IMy2; begin v1 := TMy1.Create; v1.Method_A; v1.Method_B; v1.Method_My1; v2 := TMy2.Create; v2.Method_A; v2.Method_B; v2.Method_My2; end; end.
四、委托实现:
接口中的方法是肯定要实现的, 但也可以通过 implements 关键字借用(或叫委托)其它的实现;
但, 官方文档说这只适用于 Win32. 就是说这种方法在 Win64 和其它系统都不行, 还学它干嘛?
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
2011-01-03 学用 ASP.Net 之 System.DateTime 结构
2011-01-03 学用 ASP.Net 之 System.Math 类
2011-01-03 学用 ASP.Net 之 System.Random 类
2010-01-03 GdiPlus[60]: 图像(十二) IGPImageAttributes 的更多方法
2009-01-03 C# 语法练习(15): 接口
2009-01-03 C# 语法练习(14): 类[六] - 事件
2009-01-03 如何在 "万一的 Delphi 博客" 回复自动格式化的着色代码?