Class Basics
The CLASS declaration in Object Pascal is the fundamental object-oriented feature that groups fields, methods, and properties into a single type. Instances are created with the constructor (Create) and freed with the destructor (Destroy). Inheritance and polymorphism are supported, and all classes implicitly inherit from TObject.
Syntax
{ -----------------------------------------------
CLASS declaration (TYPE section)
----------------------------------------------- }
type
TClassName = class(TParentClass)
private
{ fields accessible only from within the class }
FFieldA : TypeA;
FFieldB : TypeB;
public
{ constructor — creates an instance }
constructor Create(arg: Type);
{ destructor — frees the instance }
destructor Destroy; override;
{ methods }
procedure MethodName;
function FunctionName: ReturnType;
{ properties }
property PropName: Type read FFieldA write FFieldA;
end;
{ -----------------------------------------------
Method implementation (implementation section)
----------------------------------------------- }
constructor TClassName.Create(arg: Type);
begin
inherited Create; { call the parent class constructor }
FFieldA := arg;
end;
destructor TClassName.Destroy;
begin
{ release any dynamically allocated resources }
inherited Destroy; { call the parent class destructor last }
end;
{ -----------------------------------------------
Creating and freeing an instance
----------------------------------------------- }
var
obj : TClassName;
begin
obj := TClassName.Create(arg);
try
obj.MethodName;
finally
obj.Free; { safely calls Destroy }
end;
end.
Syntax Reference
| Syntax / Keyword | Description |
|---|---|
class(TParentClass) | Declares a class. When the parent class is omitted, TObject is automatically inherited. |
private | Section for declaring members accessible only from within the class. |
public | Section for declaring members accessible from outside the class. |
protected | Section for declaring members accessible from the class itself and derived classes. |
constructor Create | A special method called automatically when an instance is created. Invoked with TClassName.Create(...). |
destructor Destroy | A special method called automatically when an instance is freed. Override it with the override keyword. |
inherited | Calls the method of the same name from the parent class. Must be called in constructors and destructors. |
obj.Free | A safe method that checks for nil before calling Destroy. Use this instead of calling Destroy directly. |
try ... finally | Ensures that Free in the finally block is always executed even if an exception occurs. |
property | Encapsulates access to a field using read / write specifiers. |
| Field naming convention | Private fields are conventionally prefixed with F in Object Pascal (e.g., FName). |
Common Mistakes
Not calling inherited Create in the constructor
Without calling the parent class constructor, the parent class is not initialized. Make it a habit to call inherited Create; even when inheriting from TObject.
{ Problematic code — inherited Create is omitted }
constructor TFighter.Create(const AName: string);
begin
{ TObject is not initialized because inherited Create; is not called }
FName := AName;
end;
{ Correct code }
constructor TFighter.Create(const AName: string);
begin
inherited Create; { always call the parent constructor first }
FName := AName;
end;
Memory leak when try..finally is missing
If an exception occurs after obj := TMyClass.Create;, without try..finally, obj.Free is never called and a memory leak occurs. Always use the try..finally..obj.Free..end pattern.
{ Problematic code — Free is not called when an exception occurs }
var
fighter : TFighter;
begin
fighter := TFighter.Create('Kyo Kusanagi');
fighter.PrintInfo; { if an exception occurs here, fighter.Free is never called }
fighter.Free;
end.
{ Correct code — finally ensures Free is always called }
var
fighter : TFighter;
begin
fighter := TFighter.Create('Kyo Kusanagi');
try
fighter.PrintInfo;
finally
fighter.Free; { always executed even if an exception occurs }
end;
end.
Sample Code
kof_class.pas
{$mode objfpc}
{ kof_class.pas — demonstrates the basics of CLASS in Object Pascal }
{ Represents KOF (The King of Fighters) fighters as classes }
{
Compile and run:
fpc kof_class.pas && ./kof_class
}
program kof_class;
type
TFighter = class(TObject)
private
FName : string;
FTeam : string;
FPower : Integer;
FIsActive : Boolean;
public
constructor Create(const AName, ATeam: string; APower: Integer);
destructor Destroy; override;
procedure PrintInfo;
procedure SetPower(APower: Integer);
function GetGreeting: string;
property Name : string read FName;
property Team : string read FTeam;
property Power : Integer read FPower write FPower;
property IsActive : Boolean read FIsActive write FIsActive;
end;
constructor TFighter.Create(const AName, ATeam: string; APower: Integer);
begin
inherited Create;
FName := AName;
FTeam := ATeam;
FPower := APower;
FIsActive := True;
WriteLn('[Created] ', FName, ' has entered the field.');
end;
destructor TFighter.Destroy;
begin
WriteLn('[Freed] ', FName, ' has left the field.');
inherited Destroy;
end;
procedure TFighter.PrintInfo;
begin
WriteLn(' Name : ', FName);
WriteLn(' Team : ', FTeam);
WriteLn(' Power : ', FPower);
if FIsActive then begin
WriteLn(' Status : Active');
end else begin
WriteLn(' Status : Retired');
end;
end;
procedure TFighter.SetPower(APower: Integer);
begin
if APower < 0 then APower := 0;
if APower > 100 then APower := 100;
FPower := APower;
end;
function TFighter.GetGreeting: string;
begin
GetGreeting := FName + ' (' + FTeam + ') — entering!';
end;
var
fighters : array[1..5] of TFighter;
i : Integer;
begin
WriteLn('===== KOF Fighter Registration =====');
WriteLn('');
fighters[1] := TFighter.Create('Kyo Kusanagi', 'Japan Team', 95);
fighters[2] := TFighter.Create('Iori Yagami', 'Yagami Team', 94);
fighters[3] := TFighter.Create('Terry Bogard', 'Fatal Fury Team', 90);
fighters[4] := TFighter.Create('Mai Shiranui', 'Women Fighters Team', 85);
fighters[5] := TFighter.Create('Leona Heidern', 'Ikari Team', 88);
WriteLn('');
WriteLn('===== Fighter Information =====');
try
for i := 1 to 5 do begin
WriteLn('');
fighters[i].PrintInfo;
end;
WriteLn('');
WriteLn('===== Greeting Messages =====');
for i := 1 to 5 do begin
WriteLn(' ', fighters[i].GetGreeting);
end;
WriteLn('');
WriteLn('===== Power Update =====');
fighters[1].SetPower(99);
WriteLn(' ', fighters[1].Name, ' power updated to 99.');
fighters[2].IsActive := False;
WriteLn(' ', fighters[2].Name, ' has retired.');
WriteLn('');
WriteLn('===== Updated Status =====');
WriteLn('');
fighters[1].PrintInfo;
WriteLn('');
fighters[2].PrintInfo;
finally
WriteLn('');
WriteLn('===== Freeing Instances =====');
for i := 1 to 5 do begin
fighters[i].Free;
end;
end;
WriteLn('');
WriteLn('===== Done =====');
end.
fpc kof_class.pas && ./kof_class Free Pascal Compiler version ... Linking ./kof_class ===== KOF Fighter Registration ===== [Created] Kyo Kusanagi has entered the field. [Created] Iori Yagami has entered the field. [Created] Terry Bogard has entered the field. [Created] Mai Shiranui has entered the field. [Created] Leona Heidern has entered the field. ===== Fighter Information ===== Name : Kyo Kusanagi Team : Japan Team Power : 95 Status : Active Name : Iori Yagami Team : Yagami Team Power : 94 Status : Active Name : Terry Bogard Team : Fatal Fury Team Power : 90 Status : Active Name : Mai Shiranui Team : Women Fighters Team Power : 85 Status : Active Name : Leona Heidern Team : Ikari Team Power : 88 Status : Active ===== Greeting Messages ===== Kyo Kusanagi (Japan Team) — entering! Iori Yagami (Yagami Team) — entering! Terry Bogard (Fatal Fury Team) — entering! Mai Shiranui (Women Fighters Team) — entering! Leona Heidern (Ikari Team) — entering! ===== Power Update ===== Kyo Kusanagi power updated to 99. Iori Yagami has retired. ===== Updated Status ===== Name : Kyo Kusanagi Team : Japan Team Power : 99 Status : Active Name : Iori Yagami Team : Yagami Team Power : 94 Status : Retired ===== Freeing Instances ===== [Freed] Kyo Kusanagi has left the field. [Freed] Iori Yagami has left the field. [Freed] Terry Bogard has left the field. [Freed] Mai Shiranui has left the field. [Freed] Leona Heidern has left the field. ===== Done =====
kof_simple_class.pas
An example of a simple class without inheritance. TObject is inherited automatically.
{$mode objfpc}
{
Compile and run:
fpc kof_simple_class.pas && ./kof_simple_class
}
program kof_simple_class;
type
TScore = class
private
FPlayer : string;
FPoints : Integer;
public
constructor Create(const APlayer: string; APoints: Integer);
destructor Destroy; override;
procedure Show;
property Player : string read FPlayer;
property Points : Integer read FPoints write FPoints;
end;
constructor TScore.Create(const APlayer: string; APoints: Integer);
begin
inherited Create;
FPlayer := APlayer;
FPoints := APoints;
end;
destructor TScore.Destroy;
begin
inherited Destroy;
end;
procedure TScore.Show;
begin
WriteLn(FPlayer, ': ', FPoints, ' pt');
end;
var
s : TScore;
begin
s := TScore.Create('Kyo Kusanagi', 9800);
try
s.Show;
s.Points := 10000;
s.Show;
finally
s.Free;
end;
end.
fpc kof_simple_class.pas && ./kof_simple_class Free Pascal Compiler version ... Linking ./kof_simple_class Kyo Kusanagi: 9800 pt Kyo Kusanagi: 10000 pt
kof_property_class.pas
An example of using getter/setter properties to control access to fields.
{$mode objfpc}
{
Compile and run:
fpc kof_property_class.pas && ./kof_property_class
}
program kof_property_class;
type
TFighterPower = class
private
FName : string;
FPower : Integer;
function GetPower: Integer;
procedure SetPower(AValue: Integer);
public
constructor Create(const AName: string; APower: Integer);
destructor Destroy; override;
procedure ShowPower;
property Name : string read FName;
{ getter/setter clamps the value to the range 0..100 }
property Power : Integer read GetPower write SetPower;
end;
constructor TFighterPower.Create(const AName: string; APower: Integer);
begin
inherited Create;
FName := AName;
SetPower(APower);
end;
destructor TFighterPower.Destroy;
begin
inherited Destroy;
end;
function TFighterPower.GetPower: Integer;
begin
GetPower := FPower;
end;
procedure TFighterPower.SetPower(AValue: Integer);
begin
if AValue < 0 then AValue := 0;
if AValue > 100 then AValue := 100;
FPower := AValue;
end;
procedure TFighterPower.ShowPower;
begin
WriteLn(FName, ' — Power: ', FPower);
end;
var
f : TFighterPower;
begin
f := TFighterPower.Create('Iori Yagami', 94);
try
f.ShowPower;
f.Power := 150; { values above 100 are clamped }
f.ShowPower;
f.Power := -10; { values below 0 are clamped }
f.ShowPower;
finally
f.Free;
end;
end.
fpc kof_property_class.pas && ./kof_property_class Free Pascal Compiler version ... Linking ./kof_property_class Iori Yagami — Power: 94 Iori Yagami — Power: 100 Iori Yagami — Power: 0
Overview
The CLASS declaration in Object Pascal uses private / public / protected sections to control member access, and manages the instance lifecycle with the constructor (Create) and destructor (Destroy). The destructor must be overridden with override, and inherited Destroy must be called to ensure the parent class cleanup runs. For freeing instances, use Free (which includes a nil check) rather than calling Destroy directly. Wrap dynamically created instances in a try...finally block to guarantee that Free is always called even when an exception occurs. For managing classes across multiple files, see UNIT (unit basics). For applying pointers to dynamic data structures, see NEW / DISPOSE (dynamic memory allocation and deallocation).
If you find any errors or copyright issues, please contact us.