In practical Pascal programming (especially in Delphi and Lazarus), you almost never write everything in a single program file. Instead, code is organized into separate files called Units, enabling Modular Programming.
1. The Unit Structure
A Unit is a fundamental structure for organizing code, data, and type definitions. It consists of three main sections: Header, Interface, and Implementation.
unit MyUtils; // 1. Unit Header (Must match the file name: MyUtils.pas)
interface // 2. Interface Section (The 'Public' part)
uses
SysUtils; // Libraries needed by the Interface or Implementation
// All types, variables, procedures, and functions declared here
// are PUBLIC and accessible to any other unit that uses MyUtils.
type
TMyRecord = record
Data: Integer;
end;
function Add(A, B: Integer): Integer; // Only the HEADER is here
implementation // 3. Implementation Section (The 'Private' part)
// Full DEFINITION of functions/procedures declared in the interface
function Add(A, B: Integer): Integer;
begin
Result := A + B;
end;
end. // 4. Termination (Must end with a period!)
2. Breakdown of Unit Sections
| Section | Purpose | Visibility | Key Content |
| Header | Names the unit. Must match the filename (e.g., unit MyUtils; in MyUtils.pas). | N/A | unit UnitName; |
| Interface | Defines the public contract of the unit. Other units see only what is declared here. | Public | uses, type declarations, var declarations, Procedure/Function headers. |
| Implementation | Contains the private working details. Includes the full code definition for routines declared in the interface. | Private | Full Procedure/Function bodies, var declarations for local use only. |
3. Using Other Units (The uses Clause)
The uses clause tells the compiler to include functionality from another unit. It can appear in two locations:
A. Global uses (Interface Section)
- The required unit’s functions are available in both the
interfaceandimplementationsections. - Best Practice: Only put units here if they are absolutely needed for type declarations in the interface (e.g., if a public function uses a type defined in that unit).
B. Local uses (Implementation Section)
- The required unit’s functions are only available in the
implementationsection. - Best Practice: This is preferred. It speeds up compilation and reduces unnecessary dependencies for units that only use the imported unit’s code privately.
unit MyCalculations;
interface
// uses clause here (Global)
implementation
uses Math; // Local uses clause (Only implementation can use Math functions)
function PowerOfTwo(Value: Integer): Integer;
begin
// Uses the Power function from the 'Math' unit
Result := Round(Power(2, Value));
end;
end.
4. Initialization and Finalization (Optional)
The initialization and finalization blocks are optional sections that run automatically when the program starts or stops.
initialization: Code in this block runs the moment the unit is loaded into memory (before the main program’sbeginblock). Use this for setup tasks.finalization: Code in this block runs automatically when the program is shutting down. Use this for cleanup tasks, such as freeing memory or closing files.
implementation
// ... function definitions ...
initialization
Writeln('MyUtils unit is initializing resources...');
// Initialize global variables here
finalization
Writeln('MyUtils unit is cleaning up...');
// Free resources here
end.
Order of Execution: Units are initialized in the order they appear in the
usesclause, but they are finalized in the reverse order.
5. Creating and Using a Unit
- Create: In Lazarus/Delphi, go to File $\rightarrow$ New $\rightarrow$ Unit. Save it (e.g.,
MathUnit.pas). - Define: Put your reusable functions (like
AddIntegers) in the unit’s interface. - Use: In your main program file (
.lpror.dpr), add the unit name to theusesclause:Delphiprogram MainProject; uses MathUnit; // Import the unit begin Writeln(MathUnit.AddIntegers(10, 5)); // Use the function end.
