Идентификаторы с квалификацией модуля

Похоже на пространства имен в 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;
// Явно указать TColor из Graphics, чтобы избежать перекрытия одноименным типом
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 и предотвращает конфликты имен.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *