Nell'articolo precedente, abbiamo visto come definire una classe con l'uso del costrutto class
, le sue proprietà e metodi. L'esempio di classe Person
, era composta da una proprietà $name
privata ed una serie di metodi con visibilità pubblica. Un aspetto molto importante nella programmazione ad oggetti, riguarda proprio l'incapsulamento e la visibilità di proprietà e metodi.
Public, protected e private
In PHP, così come in altri linguaggi orientati agli oggetti (C++ e Java), è possibile stabilire le restrizioni su proprietà e metodi tramite i seguenti indicatori di visibilità:
Indicatore | Descrizione |
---|---|
public |
I membri (proprietà o metodi) dichiarati public sono accessibili sia dall'interno che dall'esterno della classe e dalle classi derivate da essa (viene quindi introdotto il concetto di ereditarietà di cui parleremo nei prossimi capitoli). |
protected |
I membri dichiarati protected , possono essere utilizzati all'interno della classe stessa e all'interno delle classi derivate, ma non sono accessibili dall'esterno della classe. |
private |
I membri dichiarati private , possono essere utilizzati soltanto all'interno della classe stessa. |
Tramite gli indicatori di visibilità, possiamo introdurre nuove regole all'interno delle nostre applicazioni, rendendole più robuste e maggiormente mantenibili. A questo proposito vediamo ora degli esempi pratici che ci aiuteranno a capire le differenze che si ottengono dal comportamento di proprietà e metodi quando vengono dichiarati con uno specifico indicatore di visibilità.
Prima di dichiarare il membro di una classe bisognerà specificare uno dei 3 indicatori di accesso. Nel caso in cui non si specifichi la visibilità associata ad un membro, il livello impostato di default sarà public
.
Public
Le proprietà e i metodi dichiarati public
, non presentano nessun tipo di restrizione, e sono utilizzabili da tutte le classi. L'esempio seguente mostra il codice necessario per svolgere una semplice funzione, la stampa di un nominativo:
<?php
class Person {
public $name;
public function __construct($name)
{
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
$customer1 = new person("Giuseppe Rossi");
echo "Cliente: ".$customer1->getName()."<br>";
?>
In questo caso sarà possibile accedere ai membri pubblici sia dall'esterno di un oggetto, tramite
$customer1->getName();
e sia all'interno del metodo getName()
, attraverso la variabile speciale $this
.
Private
I membri dichiarati private
sono accessibili e modificabili soltanto all'interno delle classi che li dichiarano, cosi come i metodi privati sono richiamabili solo al loro interno.
Infatti, questi sono simili ai membri protected
con la sola differenza che, le proprietà private
, sono invisibili alle classi che ereditano. Estendiamo l'esempio effettuato in precedenza allo scopo di gestire un maggior numero di informazioni, ma adottando indicatori di visibilità differenti per i membri:
<?php
class Person {
public $name;
private $age;
public function __construct($name, $age)
{
$this->name = $name;
$this->age = $age;
}
private function get_age(){
return $this->age;
}
public function print_age(){
return $this->get_age();
}
}
$customer1 = new Person("Giuseppe Rossi","34");
echo "Nome: " . $customer1->name."<br>";
echo "Anni: " . $customer1->print_age()."<br>";
echo "Anni: " . $customer1->age; // questo provoca un errore
?>
In questo caso, l'unico modo che abbiamo per accedere al valore della proprietà $age
, è tramite un metodo pubblico (se vogliamo accedervi dall'esterno) oppure tramite un metodo protetto (se vogliamo accedervi solo dalle classi che ereditano). Nel nostro esempio abbiamo utilizzato il metodo pubblico print_age()
.
Invece, l'istruzione:
$customer1->age;
causerà un errore poiché stiamo cercando di accedere ad una proprietà membro private
fuori dalla classe:
Nome: Giuseppe Rossi
Anni: 34
Fatal error: Cannot access private property Person::$age ...
Protected
Uno specificatore di accesso protetto, consente alla classe derivata di accedere alle funzioni membro dati o membri della classe base, mentre disabilita l'accesso globale ad altri oggetti e funzioni. Modifichiamo l'esempio già proposto introducendo un'ulteriore classe:
<?php
class Person {
protected $name;
}
class Employee extends Person {
function setName($name) {
$this->name = $name;
}
}
$employee = new Employee();
$employee->setName("Giuseppe Rossi");
$employee->name = "Giuseppe Rossi"; // questo provoca un errore in quanto $name è protected e non public
?>
Nel codice precedente, l'istruzione:
$this->name = $name;
presente nel metodo setName
, si riferisce al membro di dati $name
della classe Person
. L'accesso è possibile in quanto la variabile $name
è stata dichiarata come protected
. Inoltre, l'istruzione
$customer1->name
genera un errore, in quanto l'attributo o metodo protected, può essere utilizzato solo all'interno della classe e, a differenza di private
, nelle classi derivate.
Fatal error: Cannot access protected property Employee::$name in ...