MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Moștenirea

Moștenirea este unul dintre aspectele principale ale programării orientate pe obiecte. Moștenirea permite unei clase să preia funcționalitatea claselor existente și, dacă este necesar, să o redefinească. Dacă avem o clasă care nu are câteva funcții, este mult mai simplu să moștenim clasa existentă și să adăugăm câteva linii de cod, decât să creăm una nouă de la zero, rescriind o mulțime de cod.

Pentru a moșteni o clasă de la alta, trebuie să utilizăm operatorul extends. Este important de menționat că în PHP putem moșteni o clasă doar de la o singură clasă. Moștenirea multiplă nu este suportată.

De exemplu, să moștenim clasa Employee de la clasa Person:

<?php
class Person
{
   public $name;
   function __construct($name)
   {
       $this->name = $name;
   }
   function displayInfo()
   {
       echo "Nume: $this->name<br>";
   }
}
class Employee extends Person 
{}

$tom = new Employee("Tom");
$tom -> displayInfo();
?>

În acest caz, să presupunem că clasa Person reprezintă o persoană în general, iar clasa Employee - un angajat al unei companii. În această legătură, fiecare angajat reprezintă o persoană.

Și pentru a nu duplica același funcțional, este mai bine să moștenim clasa Employee de la clasa Person. În această pereche, clasa Person este numită clasa părinte sau clasa de bază, iar clasa Employee este clasa derivată sau clasa copil.

Deoarece clasa Employee este moștenită de la Person, pentru obiectele clasei Employee putem utiliza funcționalitatea clasei părinte Person. Astfel, pentru a crea un obiect Employee în acest caz, este apelat constructorul definit în clasa Person, care acceptă ca parametru numele persoanei:

$tom = new Employee("Tom");

De asemenea, pentru variabila de tip Employee este apelată metoda displayInfo, care este definită în clasa Person:

$tom -> displayInfo();

Suprascrierea funcționalității

Moștenind funcționalitatea clasei părinte, clasa derivată poate adăuga propriile proprietăți și metode sau poate suprascrie funcționalitatea moștenită. De exemplu, să modificăm clasa Employee, adăugând în ea date despre compania unde lucrează angajatul:

<?php
class Person
{
   public $name;
   function __construct($name)
   {
       $this->name = $name;
   }
   function displayInfo()
   {
       echo "Nume: $this->name<br>";
   }
}
class Employee extends Person 
{
   public $company;
   function __construct($name, $company)
   {
       $this->name = $name;
       $this->company = $company;
   }
   function displayInfo()
   {
       echo "Nume: $this->name<br>";
       echo "Lucrează la $this->company<br>";
   }
}

$tom = new Employee("Tom", "Microsoft");
$tom -> displayInfo();
?>

Aici, clasa Employee adaugă o nouă proprietate - $company, care stochează compania angajatului. De asemenea, clasa Employee suprascrie constructorul, în care sunt transmise datele pentru nume și companie. De asemenea, este suprascrisă metoda displayInfo. Prin urmare, pentru a crea un obiect al clasei Employee, trebuie să folosim constructorul suprascris în clasa Employee:

$tom = new Employee("Tom", "Microsoft");

Clasa derivată suprascrie constructorul clasei părinte, așa că pentru a crea un obiect al clasei derivate trebuie să folosim constructorul suprascris.

De asemenea, se va modifica comportamentul metodei displayInfo, care, pe lângă nume, va afișa și compania angajatului:

Nume: Tom
Lucrează la Microsoft

Apelarea funcționalității clasei părinte

Dacă ne uităm la codul clasei derivate Employee, putem vedea părți ale codului care repetă codul clasei Person. De exemplu, setarea numelui în constructor:

$this->name = $name;

De asemenea, afișarea numelui angajatului în metoda displayInfo:

echo "Nume: $this->name<br>";

În ambele cazuri, este vorba de o linie de cod. Totuși, ce se întâmplă dacă constructorul Employee repetă setarea nu a unei singure proprietăți, ci a unei duzini de proprietăți?

Și ce se întâmplă dacă metoda displayInfo din clasa derivată repetă mult mai multe acțiuni ale clasei părinte? În acest caz, este mult mai eficient să nu scriem codul repetitiv în clasa derivată, ci să apelăm funcționalitatea corespunzătoare a clasei părinte.

Dacă trebuie să apelăm o metodă a clasei părinte, putem folosi cuvântul cheie parent, după care folosim operatorul de rezoluție a domeniului :: și apoi metoda apelată.

De exemplu, să rescriem exemplul anterior:

<?php
class Person
{
   public $name;
   function __construct($name)
   {
       $this->name = $name;
   }
   function displayInfo()
   {
       echo "Nume: $this->name<br>";
   }
}
class Employee extends Person 
{
   public $company;
   function __construct($name, $company)
   {
       parent::__construct($name);
       $this->company = $company;
   }
   function displayInfo()
   {
       parent::displayInfo();
       echo "Lucrează la $this->company<br>";
   }
}

$tom = new Employee("Tom", "Microsoft");
$tom -> displayInfo();
?>

Acum, în constructorul Employee este apelat constructorul clasei de bază:

parent::__construct($name);

În el se face setarea numelui. Și în mod similar, în metoda displayInfo este apelată implementarea metodei clasei Person:

parent::displayInfo();

În final, vom obține același rezultat.

Este de menționat că, în realitate, cuvântul cheie parent înlocuiește numele clasei. Adică, am putea apela funcționalitatea clasei părinte și prin numele acestei clase:

class Employee extends Person 
{
   public $company;
   function __construct($name, $company)
   {
       Person::__construct($name);
       $this->company = $company;
   }
   function displayInfo()
   {
       Person::displayInfo();
       echo "Lucrează la $this->company<br>";
   }
}

Operatorul instanceof

Operatorul instanceof permite verificarea apartenenței unui obiect la o anumită clasă. În stânga operatorului se află obiectul care trebuie verificat, iar în dreapta - numele clasei. Și dacă obiectul reprezintă clasa respectivă, operatorul returnează true. De exemplu:

<?php
class Person
{
   public $name;
   function __construct($name)
   {
       $this->name = $name;
   }
   function displayInfo()
   {
       echo "Nume: $this->name<br>";
   }
}
class Employee extends Person 
{
   public $company;
   function __construct($name, $company)
   {
       Person::__construct($name);
       $this->company = $company;
   }
   function displayInfo()
   {
       Person::displayInfo();
       echo "Lucrează la $this->company<br>";
   }
}
class Manager{}

$tom = new Employee("Tom", "Microsoft");

$tom instanceof Employee;   // true
$tom instanceof Person;     // true
$tom instanceof Manager;    // false

Aici, variabila $tom reprezintă clasa Employee, de aceea $tom instanceof Employee returnează true.

Deoarece clasa Employee este moștenită de la Person, variabila $tom reprezintă, de asemenea, clasa Person (angajatul este și el o persoană).

Totuși, variabila $tom nu reprezintă clasa Manager, de aceea expresia $tom instanceof Manager returnează false.

Interzicerea moștenirii și operatorul final

În exemplul de mai sus, metoda displayInfo era suprascrisă de clasa derivată. Totuși, uneori este necesar să interzicem suprascrierea metodelor. Pentru aceasta, în clasa părinte, trebuie să specificăm metodele cu modificatorul final:

<?php
class Person
{
   public $name;
   function __construct($name)
   {
       $this->name = $name;
   }
   final function displayInfo()
   {
       echo "Nume: $this->name<br>";
   }
}
class Employee extends Person 
{
   public $company;
   function __construct($name, $company)
   {
       Person::__construct($name);
       $this->company = $company;
   }
   function displayEmployeeInfo()
   {
       Person::displayInfo();
       echo "Lucrează la $this->company<br>";
   }
}

$tom = new Employee("Tom", "Microsoft");
$tom -> displayEmployeeInfo();
?>

În acest caz, în toate clasele derivate din clasa Person nu vom putea defini o metodă cu același nume. De aceea, în acest caz, în clasa Employee este definită o nouă metodă - displayEmployeeInfo.

De asemenea, putem interzice moștenirea completă de la o clasă. Pentru aceasta, clasa respectivă trebuie definită cu modificatorul final:

final class Person
{
   public $name;
   function __construct($name)
   {
       $this->name = $name;
   }
   final function displayInfo()
   {
       echo "Nume: $this->name<br>";
   }
}

Acum nu vom putea moșteni clasa Employee (și nicio altă clasă) de la clasa Person.

← Lecția anterioară Lecția următoare →