Take your time to understand this first OOP step, because it's very important.
With the following articles we'll go more deeply, always keeping the employee example as glue over the whole discussion.
Here the code of Employee class:
unit Employee;
{$mode objfpc}{$H+}
interface
uses
Classes,SysUtils,Dialogs;
type
TEmployee = class //Employee 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 employee can SEE this zone)
//PRIVATE ATTRIBUTES
Id: integer; //Private Object Attribute
Name: string; //Private Object Attribute
Surname: string; //Private Object Attribute
//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
public //PUBLIC (Anyone can see this zone)
//PUBLIC ATTRIBUTES //Public Object Attribute (bad NO incapsulation!
//Id_public: integer; Object attributes must be private)
//...
//PUBLIC METHODS
//Constructors (Create the oblect Employee):
constructor Create(); overload; //Public Class Method
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
end;
implementation
uses unit1; // i use the unit 1 in order to get its public functions
var
Counter: integer =0; //Class Attribute !!!
//implementation of the methods here !!!
//Class Method
constructor TEmployee.Create(); overload;
begin
self.Name:='Default Name'; // self is "this" in c++ and gives the pointer of the object. Using the dot(.) makes dereference
self.Surname:='Default Surname'; // In c++ is traduced to : this->name OR (this*).name
self.Id := GetNextFreeId(); // For this reason i add the "self" at the objects. By doing this i can distinguish them from the class methods!
counter:=counter+1;
end;
//Class Method
constructor TEmployee.Create(Name_,Surname_ : string); overload; // we write "name_" and not "name" since we use "name" as atribute of the class
begin
Name:=Name_; // works fine without the self because "name_" is defined differenly from "name"
self.Surname:=Surname_;
self.Id := GetNextFreeId();
counter:=counter+1;
end;
//Class Method
Destructor TEmployee.Destroy; //override; //not needed here !!!
begin
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
Name := Name_;
end;
//Object Method
function TEmployee.GetSurname():string;
begin
result := self.Surname; //result is "return" in c++
end;
//Object Method
procedure TEmployee.SetSurname(Surname_:string);
begin
self.Surname := Surname_;
end;
//Object Method
function TEmployee.PrintMe():string;
begin
result:= 'Id : ' + inttostr(self.Id) + '; Name : '
+ self.Name + '; Surname : ' + self.Surname;
end;
end.
That's all for now!
Thank you, and see you on next article!