Trait in PHP: aggiungere metodi a una classe senza ereditarietà

Trait in PHP: aggiungere metodi a una classe senza ereditarietà

In PHP 5.4 è stato introdotto nel linguaggio un nuovo costrutto, chiamato «trait». Con i trait le classi PHP hanno finalmente potuto ereditare metodi e proprietà da più sorgenti: una risposta diretta al problema dell’ereditarietà singola.

Ecco un esempio:

php
<?php

trait PersonTrait
{

}

Come vedi, un trait somiglia molto a una classe. La differenza è che si dichiara con la parola chiave trait. Per i trait esiste una convenzione di denominazione che consiste nell’aggiungere il suffisso Trait: ti invito a seguirla quando crei i tuoi, per mantenere una struttura chiara.

A differenza di una classe, ed è la cosa da ricordare, un trait non si può estendere né implementare. E non si può nemmeno istanziare. Il loro unico scopo è arricchire le nostre classi, non sostituirle.

I trait possono avere dei metodi, esattamente come le classi. Immaginiamo una classe Person.

php
<?php
abstract class Person
{

}

La nostra classe, chiamata Person, è una classe astratta. Significa che è pensata per essere estesa da altre classi che rappresentano delle persone.

Ipotizziamo ora di voler aggiungere un metodo fireball(). Per esempio, vogliamo lanciare palle di fuoco per fare magia. Potremmo aggiungere qualcosa del genere.

php
<?php
abstract class Person
{
    public function fireball()
    {
        echo 'This Person send a fireball';
    }
}

Il problema è che non vuoi che chiunque possa lanciare una palla di fuoco, ed è qui che entrano in gioco i trait.

I trait sono perfetti per aggiungere metodi a un oggetto. Vogliamo aggiungere un trait agli umani dotati di poteri magici, quindi quello che ci serve è un PowerTrait

php
<?php

trait PowerTrait
{
    public function fireball()
    {
        echo 'This person send a fireball.';
    }
}

Abbiamo spostato il metodo fireball() nel trait. Non troverai nessun’altra differenza qui. Significa anche che possiamo togliere il metodo da Person, così.

php
<?php
abstract class Animal
{

}

Creiamo una classe Elfe che eredita da Person.

php
class Elfe extends Person
{
    private $name="Legolas"; // Sì, lo so che Legolas non lancia palle di fuoco, ma era l'unico che mi veniva in mente...
}

Abbiamo esteso Person con la classe Elfe, per quanto per ora sia vuota. Immaginiamo che gli elfi sappiano lanciare incantesimi: andiamo avanti e useremo il trait PowerTrait

php
<?php

class Elfe extends Person
{
    use PowerTrait;

private $name="Legolas";
}

La parola chiave usata per aggiungere un trait a una classe è la parola chiave use, inserendo al suo interno la dichiarazione use PowerTrait;

Proviamo a chiamare il metodo ereditato dal nostro trait.

php
<?php

// Crea un nuovo panda rosso.
$legolas = new Elfe;

// Accarezza il panda.
$legolas->fireball();

Qui abbiamo usato un solo trait, ma è del tutto possibile usarne quanti ne servono. Quello che segue, per esempio, è perfettamente valido.

php
<?php

class Elfe extends Person
{
    use PlayerTrait;
    use PowerTrait;
    use AttributTrait;

private $name="Legolas";
}

Usa i trait per arricchire le funzionalità delle tue classi. Naturalmente li puoi usare solo su PHP >= 5.4, quindi tienilo a mente.

Precedenza

Forse ti stai facendo la domanda seguente. Che cosa succede se estendiamo una classe e usiamo un trait che ha un metodo con lo stesso nome?

Guarda questo esempio:

php
<?php
trait TestTrait
{
    public function test()
    {
        echo 'Méthode d\'un trait';
    }
}

class TestClass
{
    public function test()
    {
        echo 'Méthode d\'une classe';
    }
}

Qui abbiamo un TestTrait e una TestClass. Entrambi hanno un metodo chiamato test(), che dice da dove arriva la chiamata.

È il momento di provare:

php
<?php

class Testing extends TestClass
{
    use TestTrait;
}

$test = new Testing;

$test->test();

Abbiamo creato una classe che estende la classe TestClass e usa TestTrait. Chiamando il metodo condiviso test() possiamo capire dall’output quale dei due ha la precedenza. Facciamo una prova.

code
Méthode d'un trait

vediamo che il metodo del trait ha la precedenza sul metodo della classe ereditata.

Significa che possiamo usare i trait per sostituire le funzionalità ereditate dalle classi astratte. È una cosa utile da capire se vuoi lavorare con i trait, e vale la pena sapere anche quando usare un trait php: un altro articolo del sito risponde a questa domanda.

PHP

Damien Flandrin Sviluppatore web dal 2010, creatore di Gekkode e di Email Impact. Ogni articolo è testato su un progetto reale prima della pubblicazione. Contatti
Newsletter

I nuovi test, tutorial e progetti, via e-mail.

Test riproducibili, codice versionato, risultati datati. Mai spam.