关于基于Delphi平台的接口编程入门
2008-02-23 07:14:27来源:互联网 阅读 ()
举个例子好了:有这样一个卖票服务,电影院可以卖票,歌剧院可以卖票,客运站也可以卖票,那么我们是否需要把电影院、、歌剧院和客运站都设计成一个类架构以提供卖票服务?要知道,连经理人都可以卖票,很显然不适合把经理人也包括到卖票服务的继承架构中,我们需要的只是一个共通的卖票服务。于是,卖票的服务是个接口,电影院、歌剧院什么的只要都遵循这样一个服务定义就能很好地相互交互和沟通(如果须要的话)。
如何在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这样就行。
说明(2):此GUID可选,如果要实现具有COM特性的接口的话则需要加上,Delphi中对于有GUID的接口在运行时在VMT表的预定位置生成接口的信息,如接口方法的定义、方法参数定义能详细信息。
说明(3):接口必须实现这三个函数。
2、接口的实现
接口服务是由类来实现的。
TIntfClass = class(TObject, IMyInterface)
private
FCounter: Integer;
FRefCount: Integer;
public
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
...
end;
3、获取接口
a. 使用类型转换。 如:
var aIntf: IMyInterface;
begin
aObj := TIntfClass.Create;
try
aIntf := (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会自行检查接口如果在使用后没有释放而在生成的程序里加上释放代码,但也因这样带来了问题,如下面代码:
var i: Integer; aObj: TIntfClass; aIntf: IMyInterface; begin aObj := TIntfclass.Create; try aIntf := aObj; aIntf.GetName... finally aIntf := nil; FreeAndNil(aObj); end;
上面的代码执行的话会产生存取违规错误,是因为对接口置nil时已释放接口,而FreeAndNil(aObj)会再释放aIntf一次,而在对aIntf置
nil时已释放了该对象。解决这个问题只要不让接口干扰对象的生命期就可以了,在Release中只需减引用计数而不做释放的动作。
function TIntfClass._Release: Integer;
begin
Result := InterlockedDecrement(FRefCount);
end;
5、接口的委托(Interface Delegation)
分为两种:
1. 对象接口委托
2. 类对象委托。
3. 对象接口委托,假如已有下面接口定义:
IImplInterface = interface(IInterface) function ConvertToUSD(const iNTD: Integer): Double; function ConvertToRMB(const iNTD: Integer): Double; end; 接着有一个类实现了该接口: TImplClass = class(TObject, IImplInterface) private FRefCount: Integer; public function ConvertToUSD(const iNTD: Integer): Double; ... end; implementation function TImplClass.QueryInterface(const IID: TGUID; out Obj): HResult; begin if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE; end; function TImplClass._Release: Integer; begin Result := InterlockedDecrement(FRefCount); if Result = 0 then Destroy; end; ... ...
现在有另外一个类TIntfServiceClass要实现IImplInterface接口,不用重新定义,只须使用上面的TImplClass就可以:
TIntfServiceClass = class(TObject, IImplInterface) private FImplService: IImplInterface; //FSrvObj: TImplClass; //如果是用类对象委托的话 public Constructor 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; begin FImplService := TImplClass.Create; end; constructor TIntfServiceclass.Create(aClass: TClass); var instance: TImplClass; begin instance := TImplClass(aClass.NewInstance); FImplService := instance.Create; end; destructor TIntfServiceClass.Destroy; begin FImplService := nil; //遵照TImplClass使用引用计数来控制对象生命周期,看TImplClass的Destroy实现。 inherited; end; 标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash