




已阅读5页,还剩1页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
基于Delphi的接口编程入门 为什么使用接口?举个例子好了:有这样一个卖票服务,电影院可以卖票,歌剧院可以卖票,客运站也可以卖票,那么我们是否需要把电影院、歌剧院和客运站都设计成一个类架构以提供卖票服务?要知道,连经理人都可以卖票,很显然不适合把经理人也包括到卖票服务的继承架构中,我们需要的只是一个共通的卖票服务。于是,卖票的服务是个接口,电影院、歌剧院什么的只要都遵循这样一个服务定义就能很好地相互交互和沟通(如果须要的话)。如何在Delphi中使用接口 1、声明接口IMyInterface = interface(IInterface) /说明(1)63E072DF-B81E-4734-B3CB-3C23C7FDA8EA /说明(2)function GetName(const str: String): String; stdcall;function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; /说明(3)function _AddRef: Integer; stdcall; /使接口引用数加1。function _Release: Integer; stdcall;/使接口引用数减1,当小于等于0时作释放动作。end;说明(1):如果有继承关系则在括号里填父接口,否则省却,如:IMyInterface = interface这样就行。type IInterface = interface 00000000-0000-0000-C000-000000000046 function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; end;说明(2):此GUID(全球唯一标识符)可选,如果要实现具有COM特性的接口的话则需要加上,Delphi中对于有GUID的接口在运行时在VMT表的预定位置生成接口的信息,如接口方法的定义、方法参数定义能详细信息。说明(3):接口必须实现这三个函数。2、接口的实现接口服务是由类来实现的。TIntfClass = class(TObject, /继承唯一的一个T打头的父类IMyInterface) /可继承实现多个I打头的接口privateFCounter: Integer;FRefCount: Integer;public / IMyInterface接口方法的实现function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;.end;3、获取接口a. 使用类型转换。 如:var aIntf: IMyInterface;beginaObj := TIntfClass.Create;tryaIntf := (IMyInterface(aObj);.b. 利用Delphi编译器内建机制。 如:aIntf := aObj。c. 利用对象的QueryInterface方法。如OleCheck(aObj.QueryInterface(IID, aIntf); 只能存取有GUID的COM接口。d. 利用as操作符。使用as操作符必须符合下面条件:1.接口必须明确地指定是从IInterface接口继承下来。2.必须拥有GUID值在Delphi7中接口的实现类还必须是从TInterfacedObject继承下来才行,如:TIntfClass = class(TInterfacedObject, IMyInterface)4、接口和对象生命期 因为Delphi会自行检查接口如果在使用后没有释放而在生成的程序里加上释放代码,但也因这样带来了问题,如下面代码:vari: Integer;aObj: TIntfClass;aIntf: IMyInterface;beginaObj := TIntfclass.Create;tryaIntf := aObj;aIntf.GetName.finallyaIntf := nil;FreeAndNil(aObj);end;上面的代码执行的话会产生存取违规错误,是因为对接口置nil时已释放接口,而FreeAndNil(aObj)会再释放aIntf一次,而在对aIntf置nil时已释放了该对象。解决这个问题只要不让接口干扰对象的生命期就可以了,在Release中只需减引用计数而不做释放的动作。function TIntfClass._Release: Integer;beginResult := InterlockedDecrement(FRefCount);end; 5、接口的委托(Interface Delegation)分为两种:1. 对象接口委托2. 类对象委托。. 对象接口委托,假如已有下面接口定义:IImplInterface = interface(IInterface)function ConvertToUSD(const iNTD: Integer): Double;function ConvertToRMB(const iNTD: Integer): Double;end;接着有一个类实现了该接口:TImplClass = class(TObject, IImplInterface)privateFRefCount: Integer;publicfunction ConvertToUSD(const iNTD: Integer): Double;.end;implementationfunction TImplClass.QueryInterface(const IID: TGUID; out Obj): HResult;beginif GetInterface(IID, Obj) thenResult := 0elseResult := E_NOINTERFACE;end;function TImplClass._Release: Integer;beginResult := InterlockedDecrement(FRefCount);if Result = 0 thenDestroy;end;. .现在有另外一个类TIntfServiceClass要实现IImplInterface接口,不用重新定义,只须使用上面的TImplClass就可以:TIntfServiceClass = class(TObject, IImplInterface)privateFImplService: IImplInterface;/FSrvObj: TImplClass; /如果是用类对象委托的话publicConstructor Create; overload;Destructor Destroy; override;Constructor Create(aClass: TClass); overload;property MyService: IImplInterface read FImplService implements IImplInterface;/ property MyService: TImplClass read FSrvObj implements IImplInterface; /如果是用对象委托的话。end;实现如下:constructor TIntfServiceClass.Create;beginFImplService := TImplClass.Create;end;constructor TIntfServiceclass.Create(aClass: TClass);varinstance: TImplClass;begininstance := TImplClass(aClass.NewInstance);FImplService := instance.Create;end;destructor TIntfServiceClass.Destroy;beginFImplService := nil; /遵照TImplClass使用引用计数来控制对象生命周期,看TImplClass的Destroy实现。inherited;end;6、接口和RTTIDelphi中在VMT-72位移处定义了接口哥格指针:vmtIntfTable = -72。相关函数:GetInterfaceCount; /获取接口数量。GetInterfaceTable; /获取接口表格。相关结构:TInterfaceEntry = packed recordIID: TGUID;VTable: Pointer;IOffset: Integer;ImplGetter: Integer;end;PInterfaceTable = TInterfaceTable;TInterfaceTable = packed recordEntryCount: Integer;Entries: array0.9999 of TInterfaceEntry;end;Self是指向VMT指针的指针,所以:Self.GetInterfaceTable.EntryCount等价于:aPtr := PPointer(Integeer(Pointer(Self) + vmtIntfTable);只要在声明中使用M+/M-指令就能在Delphi中编译出的程序里添加RTTI信息,如:$M+iInvokable = interface(IInterface)$M-接口的RTTI信息由TIntfMetaData记录结构定义: TIntfMetaData = recordname: String; /接口名称UnitName: String; /接口声明的程序单元名称MDA: TIntfMethEntryArray; /储存接口中方法信息的动态数组IID: TGUID; /接口的GUID值Info: PTypeInfo; /描述接口信息的指针AncInfo: PTypeInfo; /描述父代信息的指针NumAnc: Integer; /此接口继承自父代接口的方法数目end;TIntfMethEntryArray的定义如下:typeTCallConv = (ccReg, ccCdecl, ccPascal, ccStdCall, ccSafeCall);TIntfMethEntry = recordName: String; /方法名称CC: TCallConv; /调用惯例Pos: Integer; /方法在接口中的位置ParamCount: Integer; /方法的参数数目ResultInfo: PTypeInfo; /描述方法回传类型的信息指针SelfInfo: PTypeInfo; /描述方法本身的信息指针Params: TIntfParamEntryArray; /描述参数信息的动态数组HasRTTI: Boolean
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 教师招聘之《小学教师招聘》考前冲刺训练试卷及完整答案详解【全优】
- 农副食品新品种选育与繁殖技术推广创新创业项目商业计划书
- 教师招聘之《小学教师招聘》练习题库(满分必刷)附答案详解
- 教师招聘之《小学教师招聘》考试押题密卷含答案详解(预热题)
- 2025年呼伦贝尔莫力达瓦达斡尔族自治旗内蒙古大学校园引才笔试备考附答案详解
- 教师招聘之《幼儿教师招聘》含答案详解【培优b卷】
- 水利部旱情遥感监测系统建设与展望中国水利水电科学研究院
- 教师招聘之《小学教师招聘》检测卷讲解附参考答案详解(能力提升)
- 2025年教师招聘之《小学教师招聘》练习题库附答案详解【研优卷】
- 2025年工业互联网区块链智能合约安全漏洞扫描与修复技术解析报告001
- 80年血火淬炼此刻亮剑正当时:纪念中国人民抗日战争暨世界反法西斯战争胜利80周年阅兵仪式对初中生的启示-2025-2026学年初中主题班会
- 2025-2026学年西师大版(2024)小学数学一年级上册(全册)教学设计(附目录P227)
- 2025年大型集团财务审计外包服务合同风险防控条款规范
- 2025年国家保安员资格考试复习题库(附答案)
- 辅警考试真题(含答案)
- 新式茶饮基础知识培训课件
- 2025新疆天泽和达水务科技有限公司部分岗位社会招聘28人笔试模拟试题及答案解析
- 巧堆肥劳动课件
- 技术方案评审表-技术选型决策
- 万用表专业培训资料共23张课件
- 启闭机设备安装与调试施工方案
评论
0/150
提交评论