单元限定标识符

类似我们 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(string)
  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,避开GoogleMapsEngine同名类型遮蔽
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)

总结

单元限定 UnitName.Ident 不改动 uses 顺序,精准控制类型来源,这样就不会冲突了。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注