觀念說明
各單元之間可互相依賴、參照。當一個單元參照另一個單元時,被參照的單元可以宣告於interface介面區段,也能僅寫在implementation實作區段,兩者差異如下:
寫在 interface(介面區參照) 可依據被參照單元的內容,對外定義全新的公開元件(程序、自訂型別等),專案內所有其他單元皆可存取。
僅寫在 implementation(實作區參照) 使用範圍受限:被參照單元內的識別字,僅能於當前單元的實作程式碼中使用,外部無法存取。
範例
以下僅作示範,讀者尚未學習類別 class,只需先理解觀念即可。
新增單元檔 Classes.pas
unit Classes;
{$mode objfpc}{$H+}
interface
type
TObject=class;
TComponent=class(TObject)
constructor Create(AOwner:TComponent);virtual;
end;
TObject=class
destructor Destroy;virtual;
end;
implementation
constructor TComponent.Create(AOwner:TComponent);begin end;
destructor TObject.Destroy;begin end;
end.
接著於單元 AnotherUnit.pas 中進行參照
unit AnotherUnit;
{$ifdef FPC} {$mode objfpc}{$H+}{$J-} {$endif}
interface
uses
Classes;
// TComponent 類別定義在 Classes 單元,因此介面區必須參照 Classes
procedure DoSomethingWithComponent(var C: TComponent);
implementation
uses SysUtils; // 僅在實作區參照 SysUtils
procedure DoSomethingWithComponent(var C: TComponent);
begin
// FreeAndNil 來自 SysUtils,僅在實作程式內呼叫,只需於 implementation 區參照即可
FreeAndNil(C);
end;
end.Code language: JavaScript (javascript)
注意事項
1 介面區禁止雙向循環相依
不允許兩個單元同時於各自的 interface 區段互相參照對方。
原理:編譯器解析單元介面時,必須先完整解析該單元uses介面清單內所有相依單元。Pascal 嚴格遵循此規則,帶來兩大優勢:
編譯速度更快;編譯器可自動判斷哪些單元需要重新編譯,不需手動維護複雜的 Makefile 編譯腳本;修改程式碼後無須重編整個專案,就能確保所有相依項目同步更新。
2 實作區允許循環相依
只要至少其中一方僅在implementation實作區參照另一方,循環相依即為合法。
範例:單元 A 在介面區參照單元 B,單元 B 只在實作區參照單元 A,此類雙向循環架構編譯器完全支援。
Previous: Initialization與finalization
Next: 單元限定識別字