Classes and Objects

Program ClassDemo uses unit GamePlayer. After copying program ClassDemo into a new console program, copy unit GamePlayer into a text file (File – New – Text) and save it as GamePlayer.pas in the program folder. Use this method throughout this tutorial whenever we provide code in a unit.

The type definition in GamePlayer.pas is:

type
  TPlayer = class(TObject)
  private
    Name : string;
    Points : real;
  public
    procedure SetName(PlayerName : string);
    function GetName : string;
    procedure AddPoints (NewPoints : real);
    procedure ShowPoints;
    function GetPoints : real;
  end;  

The code TPlayer = class would work, with the new class being based by default on the inbuilt type TObject. However, TPlayer = class(TObject) is recommended because it makes it clear that the newly created class is derived from TObject. A class has a constructor (usually called Create) and a destructor (usually called Destroy). You should use the Free method (which calls Destroy) when you have finished using an object. This frees up the memory that was needed by the object.

The private fields (variables) Name and Points cannot be accessed directly from another unit. Instead, we use five public methods (routines). We declare these methods in the interface section then code them in the implementation section. When writing the code in the implementation section, remember to prefix the routine name with the name of the class and a dot e.g.
procedure TPlayer.SetName (PlayerName : string);.  

The code of the set procedure could be as simple as Name := PlayerName, but we include code to store the name with a capital followed by lower case letters. You could include validation code to ensure the integrity of your private fields. If you decide to change the implementation of your public routines, you should aim to do this without needing to change the code that uses the class.

NB The program runs in Delphi and Lazarus without any changes to the standard settings. In order to run it from the Free Pascal IDE, select menu item Options > Compiler then check 'Object Pascal Extension on' instead of 'Free Pascal dialect'.

program ClassDemo;
  {$APPTYPE CONSOLE}
uses
  SysUtils, GamePlayer in 'GamePlayer.pas';
var
  Player1, Player2 : TPlayer;
  Random1, Random2, i : integer;
  Name : string;

begin
  Player1 := TPlayer.Create;
  write('Please enter the forename of the first player. ');
  readln(Name);
  Player1.SetName(Name);
  Player2 := TPlayer.Create;
  write('Please enter the forename of the second player. ');
  readln(Name);
  Player2.SetName(Name);
  randomize;
  for i := 1 to 5 do
    begin
      Random1 := random(4);
      writeln(Player1.GetName,' draws number ', Random1);
      Random2 := random(4);
      writeln(Player2.GetName,' draws number ', Random2);
      writeln;
      if Random1 > Random2 then
        Player1.AddPoints(1)
      else
        begin
          if Random2 > Random1 then
            Player2.AddPoints(1)
          else
            begin
              Player1.AddPoints(0.5);
              Player2.AddPoints(0.5);
            end;
        end;
    end;
    Player1.ShowPoints;
    Player2.ShowPoints;
    writeln;
    if Player1.GetPoints > Player2.GetPoints then
        writeln (Player1.GetName, ' wins.')
      else
        begin
          if Player2.GetPoints > Player1.GetPoints then
            writeln (Player2.GetName, ' wins.')
          else
            writeln('Draw');
        end;
  Player1.Free;
  Player2.Free;
  readln;
end.

unit GamePlayer;

interface

type
  TPlayer = class(TObject)
  private
    Name : string;
    Points : real;
  public
    procedure SetName(Playername : string);
    function GetName : string;
    procedure AddPoints (NewPoints : real);
    procedure ShowPoints;
    function GetPoints : real;
  end;
  
implementation

uses
  SysUtils;

procedure TPlayer.AddPoints(NewPoints : real);
begin
  Points := Points + NewPoints;
end;

procedure TPlayer.ShowPoints;
var
  iPoints : integer;
begin
  iPoints := trunc(Points);
  write('Points for ', Name ,': ', iPoints);
  if Points - iPoints = 0.5 then
    write(CHR(171));
  writeln;
end;

procedure TPlayer.SetName(PlayerName : string);
begin
  PlayerName := lowerCase(PlayerName);
  PlayerName[1] := upCase(PlayerName[1]);
  Name := PlayerName;
end;

function TPlayer.GetName : string;
begin
  result := Name;
end;

function TPlayer.GetPoints : real;
begin
  result := Points;
end;

end.
  

Experimenting with Classes and Objects

  1. Confirm that the private fields Points and Name cannot be accessed directly from the ClassDemo program file.
  2. Confirm that TPlayer = class works instead of TPlayer = class(TObject) in unit GamePlayer.
  3. Procedure Tplayer.ShowPoints displays a score of ½ as 0½. Change the code in unit GamePlayer so that it will display without the zero.
  4. Write a simple program that uses class TPlayer. Each player could gain points by answering random sums correctly.
  5. Write your own class for keeping the score in a game of rugby or tennis and write a program to use it.
Programming - a skill for life!

Classes (including the inbuilt TQueue and TStringList), objects, inheritance and properties