Skip to content

Aggregation of Classes

As always you can download the project, from here.

And now the Employee class code; the Hat's one in the next.

unit Employee;

{$mode objfpc}{$H+}

interface

uses
  Classes,SysUtils,Dialogs,
  Hat; //Employee HAS A Hat. Aggregation

type
  TEmployee = class //Eployee is a CLASS and is child of TObject (inherited)
                    //All delphi classes have TObject as root father. This is not true in C++
		    //Thats why in delphi the Multiple inheritance DOES NOT EXIST
		    //Every class has at MAX ONE Father in Delphi

//We have :
//1. Class Attributes (var ...)
//2. Class Methods (constructors, destructor, class static)
//3. Object Attributes (id,name...)
//4. Object Methods (Get,Set...)

  private //PRIVATE ZONE (Only the Class employee can SEE this zone)

    //PRIVATE ATTRIBUTES
    Id: integer;                                           //Private Object Attribute
    Name: string;                                          //Private Object Attribute
    Surname: string;                                       //Private Object Attribute
    HatList : TList; //List of objects of TDocuments (list of TDocument)  Private Object Attribute
    //TList is a list of pointers. THats, TObject are pointers! (Casting)
    //aggregation is done here !!!

    //PRIVATE METHODS
    //procedure Fake();                                    //Private Object Method
    //...
    class function GetNextFreeId(): integer;               //Private Class Method (class->static in c++)

  protected //PROTECTED ZONE (Only the Class employee and his children can SEE this zone)

     //We will see this later on the inheritance

  public   //PUBLIC (Anyone can see this zone)

    //PUBLIC ATTRIBUTES
    //Id_public: integer;                                  //Public Object Attribute (bad NO encapsulation! Object attributes must be private)
    //...

    //PUBLIC METHODS
    //Constructors (Create the object Employee):
    constructor Create(Name_,Surname_: string); overload; //Public Class Method
    //The Overload allows you to have different versions of the same named function/procedure with different arguments
    //OVERLOAD : SAME NAME OF FUNCTION WITH DIFFERENT ARGUMENTS IN THE SAME CLASS

    //Destructor (can be only ONE) (Destroy the object Employee)
    Destructor Destroy; override;                          //Public Class Method
    //The Override must be specified since we are overriding the virtual TObject destroy method.
    //At the end of a destructor, you should call Inherited to invoke the parent destructor.
    //OVERRIDE : SAME NAME OF FUNCTION WITH SAME ARGUMENTS IN DIFFERENT CLASSES

    class function CountEmployees(): integer;              //Public Class Method (class->static in c++)

    function GetId():integer;                              //Public Object Method
    procedure SetId(Id_:integer);                          //Public Object Method
    function GetName():string;                             //Public Object Method
    procedure SetName(Name_:string);                       //Public Object Method
    function GetSurname():string;                          //Public Object Method
    procedure SetSurname(Surname_:string);                 //Public Object Method
    function PrintMe():string;                             //Public Object Method

    function GetHat(index:integer):THat;         //Public Object Method
    function GetHats():TList;         //Public Object Method
    procedure SetHat(Hat_:THat); //this function reveals aggregation since in order to add a hat the hat must be created !!!!
    procedure DeleteHat(Hat_:THat);

  end;

implementation

uses unit1;

var
  Counter: integer =0;    //Class Attribute SOS !!!

//implementation of the methods here !!!

//Class Method
constructor TEmployee.Create(Name_,Surname_: string); overload;
begin
  self.Name:=Name_;
  self.Surname:=Surname_;

  HatList := TList.Create; //Create the empty hat list !!!

  self.Id := GetNextFreeId();
  counter:=counter+1;
end;

//Class Method
Destructor TEmployee.Destroy; //override; //not needed here !!!
var i,imax : integer;
begin

  imax := self.HatList.Count-1;
  if imax>=0 then begin
    for i:=imax downto 0 do begin //from the end to the start i delete !!!
      //THat(HatList.Items[i]).Destroy; //DO NOT DESTROY THE HAT ! HAT CAN LIVE BY ITSELF (AGGREGATION)!
      //the follow is correct to add :
      THat(HatList.Items[i]).SetIsAvailable(true);
      HatList.Delete(i);  //delete documentlist cell
    end;
  end;

  HatList.Free;  //Destroy the list !!!

  counter:=counter-1;
  showmessage('Employee with Id ' + inttostr(self.Id) + ', Name ' + self.Name + ', Surname ' + self.Surname + ' is deleted');
  //Self->This in c++

  inherited; // Always call the parent destructor after running your own code
end;

//Class Method
class function TEmployee.GetNextFreeId(): integer;
var imax :integer;
begin

  imax := counter-1; //TList start from a[0] etc...
  if imax <> -1 then begin

     result := Form1.getEmployee(imax).GetId + 1; //Last element has the higher id since
                                                  //i always add elements at the last position
  end else result := 1;

end;

//Class Method
class function TEmployee.CountEmployees(): integer;
begin
  result := counter;
end;

//Object Method
function TEmployee.GetId():integer;
begin
  result := self.Id;
end;

//Object Method
procedure TEmployee.SetId(Id_:integer);
begin
 self.Id := Id_;
end;

//Object Method
function TEmployee.GetName():string;
begin
  result := self.Name;
end;

//Object Method
procedure TEmployee.SetName(Name_:string);
begin
  self.Name := Name_;
end;

//Object Method
function TEmployee.GetSurname():string;
begin
  result := self.Surname;
end;

//Object Method
procedure TEmployee.SetSurname(Surname_:string);
begin
  self.Surname := Surname_;
end;

//Object Method
function TEmployee.PrintMe():string;
var i,imax : integer;
    semployee, shat :string;
begin
  semployee := 'Id : ' + inttostr(self.Id)  + '; Name : ' + self.Name  + '; Surname : ' + self.Surname + ' ';

  imax := self.HatList.Count-1;
  if imax>=0 then begin
    for i:=0 to imax do begin
      shat :=  shat + THat(HatList.Items[i]).PrintMe + #13#10; //Print each hat
    end;
  end;

  result := semployee + #13#10 + shat;

end;

function TEmployee.GetHat(index:integer):THat;
begin
  result := THat(self.HatList.Items[index]);
end;

function TEmployee.GetHats():TList;
begin
  result := self.HatList;
end;

procedure TEmployee.SetHat(Hat_:THat);
begin
  // i do NOT create the hat
 self.HatList.Add(Hat_);
 Hat_.SetIsAvailable(false);
end;

procedure TEmployee.DeleteHat(Hat_:THat);
var i,imax : integer;
begin
  imax := self.HatList.Count-1;
  if imax>=0 then begin
    for i:=0 to imax do begin
      if THat(HatList.Items[i]).GetName = Hat_.GetName then begin
        THat(HatList.Items[i]).Destroy;  //Delete hat
        HatList.Delete(i);               //Delete the cell (hole) of the hatlist
        break;
      end;
    end;
  end;
end;

end.