Skip to content

Composition of Classes

As always you can download the whole project, from here.

Two next pages will show respectively the Employee and the Document classes code.

unit Employee;

{$mode objfpc}{$H+}

interface

uses
  Classes,SysUtils,Dialogs,
  Document; //Employee HAS A Document. COMPOSITION

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
    DocumentList : TList; //List of pointers of objects of TDocuments (list of TDocument)  Private Object Attribute
    //TList is a list of pointers. TDocuments, TObject are pointers! (Casting)
    //THIS LINE IS THE COMPOSITION !!!!!

    //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 childs can SEE this zone)

     //We will see this later on the inheritence (klhronomikothta)

  public   //PUBLIC (Anyone can see this zone)

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

    //PUBLIC METHODS
    //Constructors (Create the oblect Employee):
    constructor Create(Name_,Surname_,DocumentTipo_,DocumentDescription_ : 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 GetDocument(index:integer):TDocument;         //Public Object Method
    function GetDocuments():TList;         //Public Object Method
    procedure SetDocument(DocumentTipo_,DocumentDescription_ : string);//Public Object Method

  end;

implementation

uses unit1;

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

//implementation of the methods here !!!

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

  DocumentList := TList.Create; //Create the list !!!
  //Create a new document // I do TDocument.Create() because create is a method of class
  Doc_Obj := TDocument.Create(DocumentTipo_,DocumentDescription_);
  self.DocumentList.Add(Doc_Obj);  //Add the Document object to the DocumentList

  //DocumentList.Add( TDocument.Create(DocumentTipo_,DocumentDescription_) );

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

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

  imax := self.DocumentList.Count-1;
  if imax>=0 then begin
    for i:=imax downto 0 do begin //from the end to the start i delete !!!
      TDocument(DocumentList.Items[i]).Destroy; //Delete a document object (Casting)
      DocumentList.Delete(i);                   //delete documentlist cell
    end;
  end;

  DocumentList.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, sdocument :string;
begin
  semployee := 'Id : ' + inttostr(self.Id)  + '; Name : ' + self.Name  + '; Surname : ' + self.Surname + ' ';

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

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

end;

//extra...
function TEmployee.GetDocument(index:integer):TDocument;
begin
  result := TDocument(self.DocumentList.Items[index]); //casting..
end;

function TEmployee.GetDocuments():TList; //for the incapsulation (DocumentList is a private object attribute)
begin
  result := self.DocumentList;
end;

procedure TEmployee.SetDocument(DocumentTipo_,DocumentDescription_ : string);
var Doc_Obj : TDocument;
begin
  Doc_Obj := TDocument.Create(DocumentTipo_,DocumentDescription_); //Create a new document
  self.DocumentList.Add(Doc_Obj);  //Add the Document object to the DocumentList
end;

end.