Classes and Objects in Pascal
Object Pascal (as implemented by Free Pascal and Delphi) introduces the class keyword as a reference type distinct from the older object type. A class is always allocated on the heap and accessed through a reference, so assigning one variable to another makes both point at the same instance rather than copying data. You declare fields, methods, and properties inside a class block, then instantiate with Create, which is really just a constructor method inherited from TObject.
Cricket analogy: A class is like a franchise such as Mumbai Indians: the franchise template defines roles (captain, wicketkeeper), and every season's actual squad is a heap-allocated instance built from that template via a fresh 'Create' each auction cycle.
Inheritance, Virtual Methods, and Polymorphism
Inheritance in Pascal is expressed with type TDog = class(TAnimal), giving TDog every field and method of TAnimal plus whatever it adds. To get true runtime polymorphism you must mark base methods virtual and override them with the override keyword; calling a virtual method through a base-class reference dispatches to the most-derived implementation via the class's virtual method table (VMT). Methods declared without virtual are statically bound, so redeclaring them in a descendant only hides the parent version rather than overriding it — a common source of subtle bugs.
Cricket analogy: Marking a method 'virtual' is like a captain's 'field placement' instruction that every fielder overrides based on their specific role — a slip fielder and a boundary rider both 'override' the general instruction differently, and the umpire's call always resolves to whichever player is actually standing there.
Constructors, Destructors, and Interfaces
Constructors use the constructor keyword and are conventionally named Create; they can be overloaded with different parameter lists and should always call inherited Create first so the ancestor chain initializes properly, including setting up the VMT pointer. Destructors use destructor Destroy; override; and must call inherited Destroy last, typically wrapped in a try...finally block with FreeAndNil to guarantee cleanup even if an exception occurs mid-construction. Free Pascal also supports interface types, which declare a contract of methods with no implementation; a class implements one or more interfaces and objects can be queried or cast to an interface reference for loosely coupled, COM-style polymorphism with automatic reference counting.
Cricket analogy: A constructor is like a new player's induction into a team: the academy-level basics (inherited Create) must be completed before the franchise adds its own specific training, and a bad or interrupted induction (an exception mid-Create) means the player never properly takes the field.
type
TAnimal = class
private
FName: string;
public
constructor Create(const AName: string); virtual;
destructor Destroy; override;
function Speak: string; virtual;
property Name: string read FName;
end;
TDog = class(TAnimal)
public
function Speak: string; override;
end;
constructor TAnimal.Create(const AName: string);
begin
inherited Create;
FName := AName;
end;
destructor TAnimal.Destroy;
begin
// release any owned resources here
inherited Destroy;
end;
function TAnimal.Speak: string;
begin
Result := FName + ' makes a sound';
end;
function TDog.Speak: string;
begin
Result := FName + ' barks';
end;
var
A: TAnimal;
begin
A := TDog.Create('Rex');
try
WriteLn(A.Speak); // dispatches to TDog.Speak via VMT: 'Rex barks'
finally
A.Free;
end;
end.If you forget the override keyword when redeclaring a virtual method, Free Pascal silently hides the parent method instead of overriding it. Calling it through a base-class reference will then run the parent's version, not the derived one — enable {$WARN 5023 ON} or compile with -vw to catch these accidental hides.
- Pascal classes are heap-allocated reference types; assignment copies the reference, not the object.
- Mark base methods
virtualand derived overridesoverrideto get true runtime polymorphism via the VMT. - Methods without
virtual/overrideare statically bound and only hide, rather than override, the ancestor's method. - Constructors should call
inherited Createfirst; destructors should callinherited Destroylast. - Wrap object lifetime in
try...finallywithFree/FreeAndNilto guarantee cleanup on exceptions. - Interfaces declare method contracts with no implementation and support reference-counted, COM-style polymorphism.
TObjectis the implicit ancestor of every class, providingCreate,Free,ClassName, and other base services.
Practice what you learned
1. What must you do to a base class method for descendants to override it with runtime polymorphism?
2. What happens if a derived class redeclares a non-virtual method with the same name as its parent?
3. In Object Pascal, what is the correct order for chaining ancestor calls?
4. How does assigning one class-typed variable to another behave in Pascal?
5. What distinguishes an `interface` from a `class` in Free Pascal?
Was this page helpful?
You May Also Like
Generics in Free Pascal
Understand how Free Pascal's generic types and routines let you write reusable, type-safe containers and algorithms with `generic` and `specialize`.
Building GUI Apps with Lazarus
Learn how to build cross-platform desktop applications in Free Pascal using the Lazarus IDE, the LCL component library, and event-driven programming.
Debugging Pascal Programs
Learn practical techniques for diagnosing runtime errors, memory issues, and logic bugs in Free Pascal programs using the Lazarus debugger and compiler checks.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics