程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 用 Lazarus 開發 OPC Client 3 (關於接口/Interface),lazarusopc

用 Lazarus 開發 OPC Client 3 (關於接口/Interface),lazarusopc

編輯:Delphi

用 Lazarus 開發 OPC Client 3 (關於接口/Interface),lazarusopc


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;  // Error
end.

(dotNet也是自動釋放,後面章節也會提到如何使用dotNet而不自動釋放),在Delphi/Lazarus中這時可以選擇繼承來自TComponent,它也實現了IUnknown 但不會釋放自身。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved