單元限定識別字

概念類似 C++、Java、C# 當中的命名空間

同名識別字衝突

多個單元可定義同名型別 / 函式 / 變數,uses 清單中順序靠後的單元會覆蓋前方單元同名識別字

單元限定語法

單元名.識別字 明確標示來源,強制使用指定單元的定義,解決覆蓋造成的衝突。

uses 兩段區塊各自獨立生效

  • interface uses:僅作用於介面區段;
  • implementation uses:僅作用於實作區段,實作區段引用的單元會覆蓋介面區段單元的同名識別字

範例

建立 Graphics.pas 單元

unit Graphics;
{$mode objfpc}{$H+}

interface

type
  TColor = LongInt;
const
  clYellow = 10;
function Red(C:TColor):Integer;
function Green(C:TColor):Integer;
function Blue(C:TColor):Integer;

implementation
function Red(C:TColor):Integer; begin Result:=C shr 16; end;
function Green(C:TColor):Integer; begin Result:=(C shr 8) and 255; end;
function Blue(C:TColor):Integer; begin Result:=C and 255; end;

end.Code language: JavaScript (javascript)

接著建立另一個單元 GoogleMapsEngine.pas

unit GoogleMapsEngine;
{$mode objfpc}{$H+}

interface
type
  TColor = string; // 和 Graphics.TColor 是完全不同的型別

implementation

end.Code language: PHP (php)

此處存在兩個同名 TColor,兩者底層型別並不相同

接著撰寫主程式

program showcolor;
{$mode objfpc}{$H+}
{$apptype CONSOLE}

uses Graphics, GoogleMapsEngine;

var
  // Color: TColor; // 編譯錯誤:會取用後方 GoogleMapsEngine.TColor(字串型別)
  Color: Graphics.TColor; // 正確寫法,明確限定所屬單元

begin
  Color := clYellow;
  WriteLn(Red(Color), ' ', Green(Color), ' ', Blue(Color));
  ReadLn;
end.Code language: PHP (php)

編譯並執行

若未加上前綴 Graphics.,預設會使用 GoogleMapsEngine.TColor,原因為何?

主專案引入單元語法為 uses Graphics, GoogleMapsEngine;,GoogleMapsEngine 順序在後,因此遇到同名 TColor 時,編譯器預設採用順序靠後的 GoogleMapsEngine.TColor。

若要區分兩者,直接標註 Graphics.TColor 即可,作用等同命名空間,徹底避免衝突。

錯誤範例

介面區段與實作區段的 TColor 型別不一致,會觸發編譯錯誤

新增單元 UnitUsingColors.pas

unit UnitUsingColors;
{$mode objfpc}{$H+}
interface
uses Graphics;
procedure ShowColor(const Color: TColor);

implementation
uses GoogleMapsEngine; // 實作區段同名 TColor 覆蓋介面定義

// 此處 TColor 指向 GoogleMapsEngine.TColor
procedure ShowColor(const Color: TColor); 
begin
end;

end.Code language: JavaScript (javascript)

主程式 mydemo.dpr 引用此單元

program showcolor;
{$mode objfpc}{$H+}
{$apptype CONSOLE}

uses UnitUsingColors;

begin

end.Code language: PHP (php)

僅單純引用單元即可,不需呼叫內部函式或程序;若全程未呼叫,編譯器會跳過編譯 UnitUsingColors.pas。

錯誤成因拆解(編譯器視角):

// 介面簽章
procedure ShowColor(const Color: Graphics.TColor);
// 實作簽章
procedure ShowColor(const Color: GoogleMapsEngine.TColor);Code language: JavaScript (javascript)

修改為以下寫法

unit UnitUsingColors;
{$mode objfpc}{$H+}
interface
uses Graphics;
procedure ShowColor(const Color: TColor);
implementation
uses GoogleMapsEngine;
// 明確指定來自 Graphics 的 TColor,避開同名型別遮蔽
procedure ShowColor(const Color: Graphics.TColor);
begin
end;
end.Code language: JavaScript (javascript)
unit UnitUsingColors;
{$mode objfpc}{$H+}
interface
uses Graphics;
procedure ShowColor(const Color: TColor);
implementation
uses GoogleMapsEngine;
// 顯式標註 Graphics.TColor,統一型別定義
procedure ShowColor(const Color: Graphics.TColor);
begin
  WriteLn(Red(Color), Green(Color), Blue(Color));
end;
end.Code language: JavaScript (javascript)

總結

單元限定語法 單元名.識別字 無需調整 uses 順序,可精準控制型別來源,徹底解決名稱衝突。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *