基于delphi的接口编程入门

上传人:小** 文档编号:93286917 上传时间:2019-07-19 格式:DOC 页数:6 大小:48KB
返回 下载 相关 举报
基于delphi的接口编程入门_第1页
第1页 / 共6页
基于delphi的接口编程入门_第2页
第2页 / 共6页
基于delphi的接口编程入门_第3页
第3页 / 共6页
基于delphi的接口编程入门_第4页
第4页 / 共6页
基于delphi的接口编程入门_第5页
第5页 / 共6页
点击查看更多>>
资源描述

《基于delphi的接口编程入门》由会员分享,可在线阅读,更多相关《基于delphi的接口编程入门(6页珍藏版)》请在金锄头文库上搜索。

1、基于Delphi的接口编程入门 为什么使用接口?举个例子好了:有这样一个卖票服务,电影院可以卖票,歌剧院可以卖票,客运站也可以卖票,那么我们是否需要把电影院、歌剧院和客运站都设计成一个类架构以提供卖票服务?要知道,连经理人都可以卖票,很显然不适合把经理人也包括到卖票服务的继承架构中,我们需要的只是一个共通的卖票服务。于是,卖票的服务是个接口,电影院、歌剧院什么的只要都遵循这样一个服务定义就能很好地相互交互和沟通(如果须要的话)。如何在Delphi中使用接口 1、声明接口IMyInterface = interface(IInterface) /说明(1)63E072DF-B81E-4734-B

2、3CB-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):如果有继承关系则在括号里填父接口,否则省却,如:IMyInterf

3、ace = 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的接口在运行时在

4、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.

5、使用类型转换。 如: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中接口的实现

6、类还必须是从TInterfacedObject继承下来才行,如:TIntfClass = class(TInterfacedObject, IMyInterface)4、接口和对象生命期 因为Delphi会自行检查接口如果在使用后没有释放而在生成的程序里加上释放代码,但也因这样带来了问题,如下面代码:vari: Integer;aObj: TIntfClass;aIntf: IMyInterface;beginaObj := TIntfclass.Create;tryaIntf := aObj;aIntf.GetName.finallyaIntf := nil;FreeAndNil(aObj)

7、;end;上面的代码执行的话会产生存取违规错误,是因为对接口置nil时已释放接口,而FreeAndNil(aObj)会再释放aIntf一次,而在对aIntf置nil时已释放了该对象。解决这个问题只要不让接口干扰对象的生命期就可以了,在Release中只需减引用计数而不做释放的动作。function TIntfClass._Release: Integer;beginResult := InterlockedDecrement(FRefCount);end; 5、接口的委托(Interface Delegation)分为两种:1. 对象接口委托2. 类对象委托。. 对象接口委托,假如已有下面接口

8、定义: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;implement

9、ationfunction 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要实现

10、IImplInterface接口,不用重新定义,只须使用上面的TImplClass就可以:TIntfServiceClass = class(TObject, IImplInterface)privateFImplService: IImplInterface;/FSrvObj: TImplClass; /如果是用类对象委托的话publicConstructor Create; overload;Destructor Destroy; override;Constructor Create(aClass: TClass); overload;property MyService: IImplI

11、nterface 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: TImplCl

12、ass;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; /获取接口

13、数量。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.GetInterfaceT

14、able.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, ccSafe

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 商业/管理/HR > 管理学资料

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号