delphi 将单元添加到接口或实现部分的区别

30byixjq  于 2023-03-08  发布在  其他
关注(0)|答案(5)|浏览(154)

如果我有一个充满常数的单位,比如...

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.


问题不在于范围、避免循环引用等,而在于编译的应用程序中的差异。
如果UnitAUnitBUnitC都使用AConsts,则编译的应用程序是否会有差异(假设在AConsts单元中的常数和其它代码之间没有名称冲突)在App1之间,其中这些UnitAUnitBUnitC接口部分都有AConsts,而App2实现部分都有AConsts

y3bcpkx1

y3bcpkx11#

不同之处在于AConsts的interface部分中允许引用的内容,在第一个AUnit中,可以使用Const4that interface部分声明一个固定大小的数组,但在第二个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不同,这种情况不常发生在常量中,通常只发生在两个标识符中,即WindowsSysUtils中定义的FindClose函数,以及TBitmap。在GraphicsWindows中定义。在这两种情况下,编译器会告诉你做错了什么,尽管它不会确切地告诉你你使用了一个有两种不同含义的标识符。你可以通过限定标识符来解决这个问题:

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

如果以上所有的注意事项都得到了解决,那么你的程序就可以正确地编译和运行,那么在哪里使用单位就没有什么区别了。在你的例子中,App 1和App 2,这两个程序将是相同的。它们不会完全相同--编译器将以不同的顺序处理东西,因此可能会把东西放在不同的位置--但是这对你的程序的执行没有影响。

k7fdbhmy

k7fdbhmy2#

我把所有的引用都放在实现部分,只把那些必须的单元名放在接口中。
我喜欢尽可能地限制一切的范围,虽然,这一政策是根据这一点。

piztneat

piztneat3#

IDE还使用在何处声明使用的方式来确定需要编译的内容。
如果接口部分使用UnitA,实现部分使用UnitB,那么如果单元B需要重新编译,则单元不会重新编译,但如果UnitA发生变化,则单元需要重新编译。
这是 Delphi 斯超快建造速度的秘密之一。
至于你完成的可执行文件,我希望无论你把声明放在哪里,它的大小都是一样的(链接器很聪明,只链接你的应用程序实际使用的方法等),但是如果单元声明的顺序改变了,各种源代码的实际位置几乎肯定会改变。

ff29svar

ff29svar4#

界面中uses语句中的项目在整个单元中可见。
实现中uses语句中的项只在implementation部分可见。
示例:

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.

如果在接口部分同时使用这两个函数,则不会编译/链接。

ehxuflar

ehxuflar5#

我遵循一个规则,我把所有的东西放在接口部分,除非我需要处理循环引用的问题。这有助于带来一点清晰。一些向导在 Delphi 和“文件〉使用单位...”对话框把单位的实现部分。
除了RobKennedy强调的范围陷阱之外,其他都不重要。制定你的标准并坚持下去。

相关问题