Classe statica e normale, quali le principali differenze ?

Iniziamo questo breve articolo, con la pagina ufficiale del manuale di PHP, che tratta della parola chiave ’static’, la quale consente di definire membri statici all’interno di una classe :

http://it.php.net/ma … uage.oop5.static.php

Passiamo ora alla definizione formale di classe con membri statici:

“Le classi con membri statici vengono utilizzate per creare funzioni e dati in modo che sia possibile accedervi senza dover creare un’istanza della classe. Così facendo verranno separati i dati e le funzioni, che diverranno indipendenti dall’identità dell’oggetto. Infatti, i membri statici rimangono sempre inalterati, risultando separati dalle operazioni compiute sull’oggetto istanziato.”

Se avete usato le normali classi, saprete certamente che, una volta definite, per utilizzarle occorre crearne un’istanza. Ad esempio :

class cl_a {
  public $dt1;
public function fx1() {
echo("n<br>Fx1 appartenente alla classe cl_a!");
}
}
$obj = new cl_a(); //creazione istanza (in pratica creo un'oggetto di tipo cl_a)
$obj->dt1 = "test";
$obj->fx1();

Al contrario, con i membri statici possiamo ottenere una classe che non necessita di un’istanza, trasformandosi di fatto in una sorta di “contenitore”. Es. :

class cl_a {
  public static $dt1;
  public static function fx1() {
    echo("n<br>Fx1 appartenente alla classe cl_a!");
  }
}
//nessuna istanza, utilizzo diretto dei membri statici
cl_a::$dt1 = "test";
cl_a::fx1();

Niente istanza, nessun oggetto, solo la classe che, direttamente, espone metodi e proprietà. Bene. Ma a cosa può servire?

In realtà non c’è qualcosa che può essere fatta solo con le classi statiche. Non sono indispensabili. Ma alle volte, sono molto comode. Una delle cose che si possono fare con i membri statici, è la gestione dei “Singleton”. Simpatico termine che descrive una classe con una sola istanza, la quale riesce a fornire un singolo punto di accesso globale. Di seguito riporto un’esempio, preso dal del manuale (indicato all’inizio) :

class Singleton {
    private static $instance=null;
    private $value=null;
    private function __construct($value) {
        $this->value = $value;
    }
    public static function getInstance() {
        //self consente di accedere ai membri statici della classe
        if ( self::$instance == null ) {
            echo "n<br>new<br>";
            self::$instance = new Singleton("values");
        } else {
            echo "n<br>old<br>";
        }
        return self::$instance;
    }
}
$x = Singleton::getInstance();
var_dump($x); // ritorna il nuovo oggetto creato
$y = Singleton::getInstance();
var_dump($y); // ritorna sempre lo stesso oggetto creato inizialmente

Ma cosa me ne faccio di un singleton? Personalmente, molte volte lo utilizzo per racchiudere tutte le configurazioni del software, sia per le applicazioni web sia per quelle standalone, in modo che, in qualsiasi punto del programma io “mi trovi”, possa sempre accedere ad esse.

E poi? Un’altro utilizzo che è possibile fare dei membri statici è quello di condivisione dei dati tra tutti gli oggetti di una certa classe. Vediamo un’esempio :

class cl_a {
  public static $nome;
  
  public function leggi_nome()
  {
    echo("n<br> L'attuale nome è : ".self::$nome);
  }
  
  public function scrivi_nome($nuovoNome)
  {
    self::$nome = $nuovoNome;
  }
}
$obj1 = new cl_a(); //primo oggetto
$obj2 = new cl_a(); //secondo oggetto
cl_a::$nome = "Roberto";
$obj1->leggi_nome(); //stamperà "Roberto"
$obj2->leggi_nome(); //stamperà "Roberto"
$obj2->scrivi_nome("Richard"); //il secondo oggetto modifica il dato statico
$obj1->leggi_nome(); //stamperà "Richard"
$obj2->leggi_nome(); //stamperà "Richard"

In pratica, essendo tutti i dati statici condivisi fra tutte le istanze della classe, ognuna di loro può farne ciò che desidera.

Parliamo poi delle funzioni statiche. Solitamente vengono usate per operare sui dati statici della classe, per gestire (come visto sopra) i singleton, ed in genere quando non è necessario lavorare sui membri di oggetti istanziati.

Esempio pratico :

class ConvertitoreTemperature
{
  public static function c_f($temperaturaC)
  {
      // Converte da Celsius a Fahrenheit.
      $f = ($temperaturaC * 9 / 5) + 32;
      return $f;
  }
  public static function f_c($temperaturaF)
  {
      // Converte da Fahrenheit a Celsius.
      $c = ($temperaturaF - 32) * 5 / 9;
      return $c;
  }
}
$temperaturaCelsius = 15;
$temperaturaFahrenheit = 239;
echo("n<br> ".$temperaturaCelsius." gradi Celsius corrispondono a ".
     ConvertitoreTemperature::c_f($temperaturaCelsius).
     " gradi Fahrenheit");
echo("n<br> ".$temperaturaFahrenheit." gradi Fahrenheit corrispondono a ".
     ConvertitoreTemperature::f_c($temperaturaFahrenheit).
     " gradi Celsius");

Ecco l’output prodotto :

15 gradi Celsius corrispondono a 59 gradi Fahrenheit
239 gradi Fahrenheit corrispondono a 115 gradi Celsius

Infine, si può dire che, con un po di fantasia, è possibile utilizzare la parola chiave ’static’ in moltissime situazioni. Rimane comunque il programmatore a dover decidere se sia il caso o meno di utilizzarla. C’è da sottolineare il fatto che, l’uso di un costrutto (nel nostro caso ’static’), qualsiasi sia il linguaggio utilizzato, non è obbligatorio ma dipende fortemente dalle abitudini e della logica seguita dallo sviluppatore. Di conseguenza non mi sento di affermare che ci siano casi in cui l’uso di ’static’ sia più corretto, rispetto all’uso di altre tecniche.

In poche parole, se ’static’ piace e lo si trova utile per semplificare o rendere più chiaro il programma che si sta scrivendo è bene farne uso, al contrario, se il programmatore ritiene che la sua presenza possa confondere o complicare il software, ritengo giusto evitarlo.