Introdotti in PHP 5.4 ma ignorati per anni, i Trait sono un costrutto molto utile perché ci aiuteranno ad estendere le funzionalità di una classe, come per l’ereditarietà, ma senza tutte le implicazioni connesse a questa tecnica. Un Trait consiste in una serie di metodi e proprietà che possono essere utilizzati da una classe.
Il miglior modo per capire i Trait è considerarli come una sorta di copia e incolla assistito che PHP ci mette a disposizione.
Quando definiremo un Trait lo faremo proprio come se fosse una classe, implementando metodi e proprietà. Una classe potrà poi utilizzare questo e più Trait contemporaneamente per includere automaticamente il loro codice.
<?php
trait Poligono {
public $x;
function quadrato() {
echo "Disegno un quadrato!";
}
function rettangolo() {
echo "Disegno un rettangolo!";
}
}Vediamo che la definizione di un Trait è identica a quella di una comune Classe, tranne che per la keyword trait. Per far sì che una classe possa sfruttare i metodi quadrato() e poligono() e la proprietà $x utilizziamo, all’interno della Classe, la keyword use seguita dal nome del Trait. Piccolo consiglio: è buona regola definire un solo Trait per file.
<?php
class Disegno {
use Poligono;
}
$test = new Disegno;
$test->rettangolo();
// Disegno un rettangolo!Una volta che nella classe Disegno abbiamo deciso di utilizzare il Trait Poligono, i suoi metodi (e proprietà) saranno disponibili direttamente, proprio come se li avessimo copiati e incollati. Non possiamo quindi modificarli direttamente.
Una regola fondamentale che dobbiamo tenere presente è che se la Classe ha già un metodo o una proprietà con lo stesso nome che il Trait utilizza, il membro del Trait avrà la precedenza.
Sarà anche possibile utilizzare più Trait allo stesso tempo separando i nomi dei Trait con una virgola:
<?php
class Disegno {
use Poligono, Cerchio;
}Ok, ma cosa succede se entrambi questi Trait hanno, ipotizziamo, un metodo chiamato annullaTutto()? PHP genererà un fatal error. Vediamo quindi come dire a PHP di utilizzare il metodo di un Trait anziché l’altro tramite la keyword insteadof:
<?php
trait Poligono {
function annullaTutto() {
echo "Annullo il Poligono";
}
}
trait Cerchio {
function annullaTutto() {
echo "Annullo il Cerchio";
}
}
class Disegno {
use Poligono, Cerchio {
Poligono::annullaTutto insteadof Cerchio;
}
}
$test = new Disegno;
$test->annullaTutto(); // Annullo il PoligonoAbbiamo detto, quindi, alla classe Disegno di utilizzare il metodo annullaTutto() che abbiamo ottenuto dal trait Poligono anziché quello del trait Cerchio.