Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 18 di 50
  • livello avanzato
Indice lezioni

Classi anonime in PHP

Cosa sono e come si utilizzano le classi anonime in PHP, delle classi prive di nome che non possono essere estese da altre classi.
Cosa sono e come si utilizzano le classi anonime in PHP, delle classi prive di nome che non possono essere estese da altre classi.
Link copiato negli appunti

Le funzioni anonime, come abbiamo visto, sono supportate dalla versione 5.3.0 di PHP e forniscono una serie di vantaggi, tanto è vero che sono presenti in molti linguaggi di programmazione come ad esempio Javascript (si pensi ad un handler per un evento) e Python (le funzioni lambda).

Oltre a queste PHP ha introdotto le classi anonime che hanno in comune con le funzioni il fatto di non essere associate ad un nome e quindi non poter essere istanziate più di una volta tramite il costrutto new. Inoltre non possono essere estese da altre classi comportandosi essenzialmente come delle classi final e questa è una limitazione importante per l'utilizzo che se ne può fare, anche se è intuitivo pensare che una classe anonima non nasce per essere estesa.

Per il resto possiedono tutte le caratteristiche di una classe comune, per cui è possibile aggiungere metodi e proprietà pubblici, privati e protetti, possono fare uso di traits, estendere una classe base o implementare un'interfaccia. L'implementazione di un'interfaccia è probabilmente l'ambito per cui meglio si presta una classe anonima, ad esempio per finalità di testing o di prototipazione.

Dal punto di vista tecnico infatti una classe anonima in PHP è una normale classe il cui nome viene generato in maniera casuale a runtime dall'interprete PHP e che quindi cambia da un'esecuzione alla successiva. Per questo il nome della classe deve essere considerato un dettaglio sul quale non fare affidamento.

Definire una classe anonima

A differenza delle funzioni anonime non si tratta di callable in senso stretto, quindi una classe anonima non può essere assegnata di per sé ad una variabile mentre è consentito, ovviamente, assegnarvi l'oggetto istanziato da essa. Di fatto la fase della definizione e dell'istanza avvengono in contemporanea e questo spiega l'incapacità di istanziare più di una copia della stessa classe anonima.

Per la definizione dobbiamo fare ricorso alla stessa sintassi utilizzata comunemente nella programmazione ad oggetti con la differenza dell'assenza del nome:

<?php
$myObject = new class {
    private $a;
    public function set($a)
    {
        $this->a = $a;
    }
    public function get()
    {
        return $this->a;
    }
};
$myObject->set(54);
echo $myObject->get(); // 54

Come detto precedentemente è possibile fare ricorso a tutte le caratteristiche di una classe comune, quindi le seguenti sono tutte possibilità valide:

<?php
$myCar = new class extends Vehicle {};
$myCat = new class {
    use WalkableTrait;
};
$myLanguage = new class implements Language {
    public function sayHello()
    {
        return 'Ciao!';
    }
};

Passare variabili al costruttore

Gli oggetti vengono istanziati contestualmente alla definizione, quindi per passare variabili al costruttore è necessario seguire una sintassi particolare che può risultare poco intuitiva:

<?php
$myDog = new class ('dog') {
    private $name;
    public function __construct($name)
    {
        $this->name = $name;
    }
    public function whoAmI()
    {
        return 'I\'m a ' . $this->name;
    }
};
echo $myDog->whoAmI(); // I'm a dog

Istanze multiple

In realtà non è del tutto vero che non possa essere creata più di un'istanza della stessa classe anonima. Esistono infatti almeno due metodi per ottenere istanze multiple:

  • clonare l'oggetto restituito dal costrutto new e modificare successivamente il nuovo oggetto;
  • usare il pattern factory per la creazione degli oggetti.

Il pattern factory è sicuramente la soluzione più elegante e concettualmente corretta: è possibile arrivare a livelli molto complessi nella sua architettura ma l'esempio più semplice consiste nel creare una funzione simile alla seguente.

<?php
function buildMyAnimal($name)
{
    return new class($name) {
        private $name;
        public function __construct($name)
        {
            $this->name = $name;
        }
        public function whoAmI()
        {
            return 'I\'m a ' . $this->name;
        }
    };
}
$myDog  = buildMyAnimal('dog');
$myDog2 = clone $myDog;
$myCat  = buildMyAnimal('cat');
echo $myDog->whoAmI();  // I'm a dog
echo $myDog2->whoAmI(); // I'm a dog
echo $myCat->whoAmI();  // I'm a cat

All'interno della stessa esecuzione tutti gli oggetti istanziati da una classe anonima condividono la stessa classe base: è possibile quindi confrontare due oggetti derivati da classi anonime per controllare se sono dello stesso tipo. Al contrario oggetti istanziati da classi anonime diverse non condividono la stessa classe base come si può comprendere da questo esempio:

<?php
[...]
$myCar = new class {};
var_dump(get_class($myDog)  === get_class($myCat)); // true
var_dump(get_class($myDog2) === get_class($myCat)); // true
var_dump(get_class($myCat)  === get_class($myCar)); // false

Ti consigliamo anche