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.