In addition,
Each unit has two distinct parts. The interface and the implementation.
The interface section contains all public definitions (types, procedure headings, constants). The implementation section contains all implementation details.
When you use a unit, (using the uses clause) you get access to the public definitions of that unit. This access is not recursive, so if unit A interface uses unit B, and unit C uses unit A, you do not get access to unit B unless you use it explicitly.
The implementation section has access to the interface, to the unit used in both uses clauses (interface and implementation).
The interfaces of used units are compiled first before it continues compiling the rest. This has the advantage that you can have circular dependencies from within the implementation:
unit A;
interface
uses B;
unit B;
interface
implementation
uses A;
Which compiles:
- try interface A, fail need B
- try interface B, ok!
- try interface A, ok!
- try implementation A, ok!
- try implementation B, ok!
Each unit also has an initialization section (and if it has an initialization section, it could also have a finalization section.) The initialization section is used to initialize the variables of the unit. The finalization sections are used to cleanup.
When you use these, its wise not to count on initializations of other units. Just keep them simple and short.
Unit also are namespaces.
Considder the following:
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;
If an identifier is defined in multiple used units, the last unit possible in the uses list is taken. So f1 = 2. But you can prefix it with the unit (namespace) name to solve this problem.
With the introduction of .net, multi part namespaces are allowed which introduces other nice problems:
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?
In this case you have a conflict. But that is resolved by giving namespace names higher priority. So the first line fails.