向Interface使用子句而不是Implementation uses子句添加单元

时间:2009-02-09 14:57:27

标签: delphi uses-clause

使用Delphi时:如果我有一个充满常量的单位,如......

Unit AConsts;
Interface
Const
     Const1 : WideString = 'Const1';
     Const2 : WideString = 'Const2';
     Const3 : WideString = 'Const3';
     Const4 = 100;
     Const5 = 100;
Implementation
end.

我想从另一个单位使用这个单位,......之间有什么区别吗?

Unit AUnit;
Interface
Uses 
    AConsts;
Implementation
end.

Unit AUnit;
Interface
Implementation
Uses
    AConsts;
end.

? 或者换句话说,就编译的应用程序而言,两者之间是否存在差异?

[编辑1]

感谢目前为止的答案。

我没有把这个问题弄清楚,为此我道歉。问题不在于范围,避免循环引用等。它是关于编译应用程序的差异。也许另一个例子会有帮助。

如果UnitA,UnitB和UnitC都使用AConsts,那么在App1之间编译应用程序(假设AConsts单元和其他代码中的常量之间没有名称冲突)会有所不同,其中这些UnitA,UnitB和UnitC都有AConsts在Interface部分的uses子句和App2中,UnitA,UnitB和UnitC都在Implementation部分的uses子句中都有AConsts。

5 个答案:

答案 0 :(得分:10)

区别在于您可以在哪里引用AConsts在其界面部分中的内容。在第一个AUnit中,您可以使用Const4 接口部分中声明一个固定大小的数组。您无法在第二个AUnit中执行此操作,因为Const4不在范围内。

如果你不小心,可以对已编译的程序产生影响。假设我们有另一个单元,声明一个名为Const4的常量:

unit BConsts;
interface
const
  Const4 = 50;
implementation
end.

现在我们在UnitA中定义一个数组,如下所示:

unit AUnit
interface
uses BConsts;
var
  data: array[0..Pred(Const4)] of Integer;
implementation
uses AConsts;
procedure Work;
var
  i: Integer;
begin
  for i := 0 to Const4 - 1 do begin
    data[i] := 8;
  end;
end;
end.

该代码将在数组末尾之外写入,因为接口部分范围内的Const4与实现部分中使用的Const4不同。常量不会经常发生这种情况。它通常只有两个标识符,FindCloseWindows中定义的SysUtils函数以及TBitmapGraphics中定义的Windows。在这两种情况下,编译器会告诉你,你做错了什么,虽然它不会准确地告诉你你已经使用了具有两种不同含义的标识符。您可以通过限定标识符来解决问题:

for i := 0 to BConsts.Const4 - 1 do
  data[i] := 8;

如果解决了上述所有注意事项,那么您的程序会正确编译并运行,那么在使用单位时没有区别。在您的App1和App2示例中,两个程序将是相同的。它们将不相同 - 编译器将以不同的顺序处理事物,因此可能将事物放在不同的地方 - 但它对程序的执行没有影响。

答案 1 :(得分:3)

我将所有引用放在实现部分中,并且只将这些单元名称放在我必须的接口中。

尽管如此,我希望尽可能地限制所有事物的范围,而且这项政策也是如此。

答案 2 :(得分:2)

IDE还会使用您声明用途的方式来确定编译所需的内容。

如果您的接口部分使用UnitA,然后您的实施部分使用UnitB,如果B单元需要重新编译,则您的设备不会,但如果unitA发生更改,那么您的设备将需要重新编译。

这是Delphis超快速构建速度的秘密之一。

至于你已经完成的可执行文件,我希望无论你在哪里放置声明,它都会变成相同的大小(链接器很聪明,只有你的应用程序实际使用的方法等链接),但各种实际的位置如果单位声明的顺序发生变化,来源几乎肯定会改变。

答案 3 :(得分:1)

界面中uses语句中的项目在整个单元中可见。

实现中uses语句中的项只能在实现部分中看到。

示例:

unit A;
interface
const 
  cA = 1;
..


unit B;
interface
const 
  cB = 1;
..



unit C;
interface
uses
  A;
const 
  cC1 = cA;
  cC2 = cB; // Error

implementation
uses
  B;
const
  cC3 = cA;
  cC4 = cB;

end.

如果实现部分中至少包含一个单元,则可以创建相互依赖的单元:

unit A;
interface
implementation
uses
  B;
end.


unit B;
interface
implementation
uses
  A;
end.

如果两者都在接口部分使用,则不会编译/链接。

答案 4 :(得分:1)

我遵循一条规则,除非我需要处理循环引用的问题,否则我将所有内容放在接口部分上。这有助于带来一点清晰度。 Delphi中的一些向导和“File> Use Unit ...”对话框将单元放在实现部分。

除了Rob Kennedy强调的范围陷阱外,没关系。制定标准并坚持下去。