Come vengono eseguite le uguaglianze tra oggetti su PHP


Alle prese con PHP

Fin dalle scuole superiori mi è stato insegnato a programmare utilizzando il linguaggio Java. Nel corso degli anni ho provato diversi linguaggi di programmazione (python, javascript, C#...) ma alla fine, complice anche l'università, tornavo sempre a programmare con Java. Di conseguenza non deve sorprendere il fatto che Java sia il mio linguaggio di programmazione di riferimento.
Da quando sono entrato nel mondo del lavoro però mi sono trovato a dover programmare utilizzando PHP 7.
Fortunatamente il passaggio da Java a PHP è stato abbastanza indolore. La sintassi e il modo di scrivere il codice non è troppo differente tra i due linguaggi e quindi, dopo un inevitabile fase di transizione, sono riuscito a trovare aspetti che mi piacciono molto di più in PHP e cose in cui invece ancora reputo Java nettamente superiore.

Uno degli aspetti che mi ha causato più grattacapi durante la fase di transizione è stata la differenza con cui vengono gestite le uguaglianze tra variabili tra Java a PHP.
Infatti PHP è un linguaggio di scripting con tipizzazione dinamica,  mentre Java è un linguaggio di programmazione compilato fortemente tipizzato.

A causa di questa differenza nella tipizzazione del linguaggio in Java è impossibile, ad esempio, confrontare una variabile di tipo float con una di tipo int senza prima effettuare un cast esplicito.
In PHP invece, essendo tipizzato dinamicamente, quando si prova a fare una somma tra una variabile di tipo stringa e un intero il linguaggio si occupa in automatico di trovare un formato in cui le due variabili sono tra loro compatibili.
Infatti in PHP l'operazione: 5 + "2" da come risultato il numero 7. Ciò accade perché PHP riconosce il + come simbolo per l'addizione tra due numeri e cerca di convertire in maniera autonoma gli addendi in valori numerici.
La stessa operazione in Java avrebbe richiesto la conversione esplicita della stringa in un intero. Di conseguenza avrei dovuto scrivere la stessa operazione nel seguente modo:
5 + Integer.parseInt("2")

A causa di questa conversione automatica delle variabili in PHP è possibile fare confronti tra variabili che non sarebbero possibili in Java. Ad esempio, 3 == "3" PHP mi restituisce TRUE in quanto i due membri vengono prima convertiti ad intero e poi confrontati.
Per poter confrontare le variabili in modo più "strict" PHP, oltre il classico simbolo ==, mette a disposizione un altro operatore: === (identico)L'operatore === permette di svolgere il confronto tra le variabili senza provare a convertire automaticamente il tipo delle variabili. Quindi il confronto 3 === "3" fornirebbe come risultato FALSE.

Quando usare == e quando ===?

Fino a che mi limito a confrontare variabili dello stesso tipo non ci sono differenze tra l'utilizzo dell'operatore == e ===. Al più potrei dire che il secondo operatore potrebbe essere più corretto per verificare che il valore passato sia effettivamente del tipo che voglio confrontare.
Il discorso si fa molto più interessante quando si vogliono confrontare due variabili di tipo oggetto. Tramite l'operatore == viene confrontato che il contenuto degli oggetti sia il medesimo. Di conseguenza due oggetti diversi ma con le stesse variabili risultano essere uguali.
Invece con l'operatore === vengono confrontati gli handle degli oggetti.
Per capire cosa sono gli handle bisogna ripercorrere un tratto di storia di PHP. Con l'avvento di PHP 5 (nel lontano 2004) è cambiato il modo in cui vengono gestiti gli oggetti in memoria. Da questa versione in poi, quando viene creato un nuovo oggetto, questo viene memorizzato nell'object store e gli viene assegnato un numero identificativo chiamato handle. Di conseguenza, quando copio un oggetto da una variabile ad un'altra, in realtà viene semplicemente aggiunto un nuovo riferimento che punta allo stesso handle. (In questo modo è come se PHP passasse sempre gli oggetti per riferimento).
L'utilizzo dei due operatori può sembrare quasi uguale anche nel caso del confronto tra oggetti ma c'è una sottile differenza. Se ad esempio assegno ad una variabile il clone di un oggetto ho il seguente risultato:

Questo accade perchè:
  • a == b confronta le variabili dell'oggetto ed essendo le stesse restituisce true
  • a === b invece confronta gli handle degli oggetti e poichè con clone viene creato un nuovo oggetto il risultato dell'uguaglianza risulta essere false
Per ulteriori informazioni sul funzionamento degli operatori per le uguaglianze di PHP ti lascio il link alla pagina della documentazione ufficiale.

Commenti