ユニット修飾識別子

C++、Java、C#における名前空間と同様の概念です

同名識別子の競合

複数のユニットに同名の型・関数・変数を定義可能です。usesリスト内で後ろに記述したユニットが、前のユニットの同名識別子を上書きします

ユニット修飾構文

ユニット名.識別子 で参照元を明示し、指定したユニットの定義を強制的に使用して上書きによる競合を解消します。

uses の2つの記述領域はそれぞれ独立して適用されます

  • 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という同名の型が2つ存在し、型の種類が異なります

メインプログラムを記述

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として解決されます。

2つを区別したい場合は 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 の記述順を変更せず、型の参照元を精密に制御し、名称競合を防止します。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です