Object-Oriented Programming (OOP) is a programming paradigm that organizes software design around objects—data structures that bundle data (fields) and behavior (methods). This provides immense benefits in code structure, reuse, and maintainability.
1. Classes vs. Objects
- Class: A blueprint or template for creating objects. It defines the structure (fields) and behavior (methods) that all objects of that type will have. Classes are defined in the
typesection. - Object: An instance of a class. When you create an object, memory is allocated on the Heap for the data defined in the class.
2. Class Declaration and Basic Structure
Classes are derived from a base class, with TObject being the ultimate ancestor for all classes in Object Pascal. Class names typically start with the letter ‘T’ (e.g., TClient, TList).
program OOPDemo;
type
TClient = class(TObject) // Inherits from TObject (the base class)
private
// Fields and methods accessible ONLY from inside the TClient class
fName: String;
public
// Fields and methods accessible from ANY part of the program
// Constructor (to create and initialize the object)
constructor Create(const AName: String);
// Destructor (to clean up and destroy the object)
destructor Destroy; override;
procedure DisplayInfo;
end; // End of class declaration
3. Encapsulation and Access Modifiers
Encapsulation is the principle of hiding the internal workings (data/fields) of an object from the outside world. This is achieved using Access Modifiers:
| Modifier | Visibility | Usage | Best Practice |
private | Hidden. Only accessible by code within the class itself (its own methods). | Used for internal data fields that should not be changed directly. | Default for data fields (e.g., fName). |
public | Visible. Accessible from anywhere in the program. | Used for methods (functions/procedures) that define the object’s external behavior. | Default for external methods (e.g., Create, DisplayInfo). |
protected | Hidden, but inheritable. Accessible within the class itself and by any descendant classes. | Used for methods/fields needed for specialized subclasses (covered in P3.1). | N/A |
4. Constructors and Destructors
A. Constructor (Create)
The Constructor is a special method called to allocate memory for the object (on the Heap) and perform any necessary initialization of its fields.
// Implementation of the TClient constructor
constructor TClient.Create(const AName: String);
begin
// Always call the ancestor's constructor first
inherited Create;
// Initialize internal state
fName := AName;
Writeln('TClient object created for: ', fName);
end;
B. Destructor (Destroy) and Memory Management
The Destructor is a special method called to clean up any resources the object holds and eventually free the memory allocated for the object. The standard destructor is called Destroy.
Crucial Rule: Always call the object’s
Freemethod, NOTDestroydirectly. TheFreemethod is a safe wrapper that checks if the object isnilbefore callingDestroy.
// Implementation of the TClient destructor
destructor TClient.Destroy;
begin
Writeln('TClient object destroyed for: ', fName);
// Perform cleanup (e.g., close files, free other objects)
inherited Destroy; // Always call the ancestor's destructor last
end;
5. Creating and Using Objects
Creating an object requires two steps: declaring a reference variable (which is a pointer stored on the Stack) and instantiating the object (allocating the object’s data on the Heap).
procedure TClient.DisplayInfo;
begin
Writeln('Client Name: ', fName);
end;
var
ClientPtr: TClient; // ClientPtr is a reference (pointer) on the Stack
begin
// 1. Instantiation (Allocation on the Heap and calling the constructor)
ClientPtr := TClient.Create('Sophia');
// 2. Using the object (calling its methods)
ClientPtr.DisplayInfo;
// 3. Cleanup using the safe method (Crucial step!)
ClientPtr.Free;
// ClientPtr is automatically set to nil after Free, preventing double-free issues
end.
6. Memory Safety (try...finally)
Because forgetting to call Free results in a memory leak, the best practice in Object Pascal for local objects is to wrap the object usage in a try...finally block to guarantee cleanup, even if an exception occurs.
var
Worker: TClient;
begin
Worker := TClient.Create('John');
try
// Use the object here:
Worker.DisplayInfo;
// ... potentially risky code that might raise an exception ...
finally
// This block is ALWAYS executed, regardless of errors.
Worker.Free; // Guarantees the destructor is called.
end;
end;
