加えて、
各ユニットには2つの異なる部分があります。インターフェイスと実装。
インターフェイスセクションには、すべてのパブリック定義(タイプ、プロシージャの見出し、定数)が含まれています。実装セクションには、すべての実装の詳細が含まれています。
ユニットを使用すると(uses句を使用して)、そのユニットのパブリック定義にアクセスできます。このアクセスは再帰的ではないため、ユニットAインターフェイスがユニットBを使用し、ユニットCがユニットAを使用する場合、明示的に使用しない限り、ユニットBにアクセスできません。
実装セクションは、インターフェース、両方のuses句(インターフェースと実装)で使用されるユニットにアクセスできます。
使用されるユニットのインターフェースは、残りのコンパイルを続行する前に最初にコンパイルされます。これには、実装内から循環依存関係を持つことができるという利点があります。
unit A;
interface
uses B;
unit B;
interface
implementation
uses A;
コンパイルするもの:
- インターフェイスAを試してください、失敗する必要がありますB
- インターフェースBを試してみてください。
- インターフェースAを試してみてください。
- 実装Aを試してください。
- 実装Bを試してください。
各ユニットには初期化セクションもあります(初期化セクションがある場合は、ファイナライズセクションもあります)。初期化セクションは、ユニットの変数を初期化するために使用されます。ファイナライズセクションは、クリーンアップに使用されます。これらを使用するときは、他のユニットの初期化を当てにしないのが賢明です。シンプルで短くしてください。
ユニットも名前空間です。次のことを考慮してください。
unit A;
interface
const foo = 1;
unit B;
interface
const foo = 2;
unit C;
interface
uses A, B;
const
f1 = foo;
f2 = A.foo;
f3 = B.foo;
識別子が複数の使用単位で定義されている場合、使用リストで可能な最後の単位が取得されます。したがって、f1 = 2です。ただし、この問題を解決するために、ユニット(名前空間)名のプレフィックスを付けることができます。
.netの導入により、マルチパート名前空間が許可され、他の優れた問題が発生します。
unit foo;
interface
type
rec1 = record
baz : Boolean;
end;
var
bar : rec1;
unit foo.bar;
interface
var
baz : Integer;
uses
foo, foo.bar;
begin
foo.bar.baz := true;
foo.bar.baz := 1;
end.
// 1. Which these lines gives an error and why?
// 2. Does the result change if you write uses foo.bar, foo?
この場合、競合が発生します。しかし、それは名前空間名に高い優先順位を与えることによって解決されます。したがって、最初の行は失敗します。