Anche in PHP, come negli altri linguaggi orientati agli oggetti, è possibile dichiarare attributi e metodi statici di una classe. Per fare ciò basta usare la parola chiave static, anteponendola alla dichiarazione dell’attributo o del metodo, come nel seguente esempio.
<?php
// Definizione della classe MyClass
class MyClass {
public static $att; // attributo statico
// Metodo statico
public static function metodo($a){
echo $a;
}
}
?>
La possibilità di dichiarare proprietà e funzioni membro statiche non è certo una novità di PHP 5. Già in PHP 4, infatti, c’era questa possibilità. In PHP 5 le cose rimangono praticamente invariate.
Cosa significa e come usare attributi e metodi statici
Il significato di metodi e attributi statici è che essi non fanno parte degli oggetti della classe, ma della classe stessa. Essi esistono quindi indipendentemente dall’avere o meno istanziato degli oggetti della classe. Per questo motivo deve esistere un modo per accedere alle proprietà e alle funzioni statiche senza riferirsi ad un’oggetto preciso. Ciò è possibile tramite l’operatore ::.
Nell’esempio seguente viene mostrato come accedere all’attributo $att e alla funzione metodo() prima dichiarate, indipendentemente dall’avere creato un’oggetto della classe.
<?php
$a = 5;
// Imposto l'attributo statico
MyClass::$att = $a;
// Chiamo il metodo statico
MyClass::metodo($a); // Stampa 5
?>
In realtà PHP non impedisce di accedere agli attributi statici attraverso un istanza della classe, anche se è concettualmente "sbagliato". Quindi una sintassi come quella del prossimo esempio è legale, ma a mio parere da evitare:
<?php
$a = 5;
// Creo un istanza della classe
$obj = new MyClass();
// Imposto l'attributo statico
$obj->att = $a;
// Chiamo il metodo statico
$obj->metodo($a); // Stampa 5
?>
Ovviamente in questo caso è necessario utilizzare l’operatore -> e non ::, dato che si stanno utilizzando l’attributo e il metodo statici come se fossero appartenenti all’oggetto. In altri linguaggi di programmazione, come Java e C++, questo tipo di uso di metodi e attributi static avrebbe provocato dei warning in compilazione. PHP invece lascia correre.
E’ inutile dire che una classe con attributi o funzioni statiche può avere anche degli attributi e metodi non static. Bisogna ricordarsi però sempre che un attributo statico non fa parte dell’oggetto ma della classe, ed è quindi "globale" per tutti gli oggetti della classe. Per questo motivo è molto utile usare static per dichiarare ad esempio delle costanti della classe, o per implementare particolari design patter, come il Singleton.
I modificatori di visibilità per static
Come per qualsiasi altro attributo e funzione della classe, anche attributi e metodi dichiarati static possono avere visibilità private, protected e public. Il prossimo esempio chiarifica cosa è visibile all’esterno della classe.
<?php
// Definizione della classe MyClass
class MyClass {
public static $att1; // attributo statico public
protected static $att2; // attributo statico protected (visibile solo alle sottoclassi)
private static $att3; // attributo statico private (visibile solo da questa classe)
// Metodo statico public
public static function metodo1($a){
echo "pubblico".$a;
}
// Metodo statico protetto (visibile solo alle sottoclassi)
protected static function metodo2($a){
echo "protetto".$a;
}
// Metodo statico privato (visibile solo da questa classe)
private static function metodo3($a){
echo "privato".$a;
}
}
$a = 5;
// Imposto $att1, $att2, e $att3
MyClass::$att1 = $a; // Ok
MyClass::$att2 = $a; // Errore! $att2 è protected
MyClass::$att3 = $a; // Errore! $att3 è private
// Chiamo il metodo statico pubblico
MyClass::metodo1($a); // Stampa "pubblico5"
// Chiamo il metodo statico protett
MyClass::metodo2($a); // Errore! metodo2() è protected
// Chiamo il metodo statico privato
MyClass::metodo3($a); // Errore! metodo3() è private
?>
Nel caso si intenda usare static per una variabile all’interno di una funzione, il suo significato è identico a quello che aveva in PHP 4, ovvero la variabile statica non viene distrutta all’uscita dalla funzione, ma rimane valida ad ogni chiamata della funzione. Ma questo è un caso che non rientra nell’obiettivo dell’articolo, in quanto ha ben poco a che fare con il paradigma ad oggetti.