首页 > 代码库 > 用 Lazarus 开发 OPC Client 3 (关于接口/Interface)

用 Lazarus 开发 OPC Client 3 (关于接口/Interface)

Delphi/Lazarus 里面有个概念就是接口,这个概念在很多语言里面也都存在,而且发扬,dot Net 就是这样。

提到接口自然而然就想到COM、DCOM、OLE、ActiveX等相关知识,不错,确实可以应用于这些环境,而且Delphi/Lazarus中的Interface功能强大到不仅实现微软基于COM的技术,在Linux或其他系统下Interface的设计理念和方法一样可用。这里我们仅仅记录一下在Windows下的心得。

Delphi/Lazarus下面向对象设计中多态、继承、封装利用Interface的方法和Class的方法一般会有所区别,很早有本书中就提到“在设计初期就必须明确,用接口开发,还是Class开发”。那么接口到底是什么呢?在高级语言中我们可能会比较模糊,与纯抽象类有毛线区别啊,都是“方法定义嘛”!这个就要从其内部结构说说了。

其实Interface在计算机内存中就是一片连续的方法说明,整个很关键哦,也就是为什么接口定义了,就不可以再随意更改了。必须重新定义新的接口,就算加一个功能也是如此。尤其是多个程序、多中语言进行沟通更是如此。按这个逻辑推导方法的顺序也不可以随意调整哦。

Delphi/Lazarus中接口很多我们大多会继承自IUnknown /IInterface,对它们是等价的。他们其中的3个方法也是COM的基础。

该代码是 FPC 下的,所以定义了很多条件编译开关
IUnknown = interface  [{00000000-0000-0000-C000-000000000046}]  function QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;
out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; function _AddRef : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; function _Release : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};end;IInterface = IUnknown;

而我们在使用中也往往会继承 TInterfacedObject,作为实现的父类,它毕竟帮我们实现了最基本的释放功能。也就是引用记数到0就释放资源。这样问题也就来了。也就是实现了资源的自动管理,这和dotNet不是一样吗,当然不同了,dotNet毕竟是后起之秀,晚好多年咧,都是安德森设计的所以资源控制上更厉害,但万事万物都有其两面性,我有时就是不想让它自动释放!“明明是智能释放哪里会有这样的情况发生为什么不用呢,记数到0就该释放”要解释这个情况不能从简单Class来解释,需要用比较复查的结构来描叙。

Type  TGroup=class;  IGroup=interface(IUnknown)      procedure K1;  end;  IClient=interface(IUnknown)      procedure K2;  end;  TClient=class(TInterfacedObject,IClient)     public FGroup:IGroup;       procedure K1;  end;  TGroup=class(TInterfacedObject,IGroup)    public  FClient:IClient;    procedure K2;  end;var  _ClientObj:TClient;  _GroupObj:TGroup;  _Client_IF:IClient;  _Group_IF:IGroup;. . .begin  _ClientObj:=TClient.Create;  _GroupObj:=TGroup.Create;  _ClientObj.FGroup:=_GroupObj;  _GroupObj.FClient:=_ClientObj;  _Client_IF:=_ClientObj;  _Group_IF:=_GroupObj;  _Client_IF:=nil;  // OK  _Group_IF:=nil;  // Errorend.

(dotNet也是自动释放,后面章节也会提到如何使用dotNet而不自动释放),在Delphi/Lazarus中这时可以选择继承来自TComponent,它也实现了IUnknown 但不会释放自身。

用 Lazarus 开发 OPC Client 3 (关于接口/Interface)