Gli sviluppatori di PHP hanno iniziato ad intervenire sulla tipizzazione dei dati prima con la versione 5 e poi con la 7.2. Con la 7.4, il linguaggio creato da Rasmus Lerdorf, fa un importante passo avanti avvicinandosi sempre di più a linguaggi come il Java.
La novità introdotta riguarda le dichiarazioni di tipo anche per le proprietà di una classe. Il seguente codice:
class User {
/** @var int $id */
private $id;
/** @var string $name */
private $name;
public function __construct(int $id, string $name) {
$this->id = $id;
$this->name = $name;
}
public function getId(): int {
return $this->id;
}
public function setId(int $id): void {
$this->id = $id;
}
public function getName(): string {
return $this->name;
}
public function setName(string $name): void {
$this->name = $name;
}
}
con la versione 7.4 o successive potrà essere scritto nella forma seguente senza bisogno di metodi setter/getter che forzino la tipizzazione delle proprietà:
class User {
public int $id;
public string $name;
public function __construct(int $id, string $name) {
$this->id = $id;
$this->name = $name;
}
}
Questo implica che, qualora volessimo assegnare un valore diverso dal tipo definito dalla proprietà, ci verrà restituito un fatal error
$user->id = 'ciao';
Fatal error: Uncaught TypeError: Typed property User::$id must be int, string used...
Tipi di dato supportati
Sono supportati tutti i tipi, incluse le classi, ad eccezione di void e callable. L'RFC riporta una classe di esempio con tutte le possibilità a disposizione.
class Example {
// Sono supportati tutti i tipi tranne "void" e "callable"
public int $scalarType;
protected ClassName $classType;
private ?ClassName $nullableClassType;
// I tipi sono consentiti anche nelle proprietà statiche
public static iterable $staticProp;
// I tipi possono essere utilizzati con la notazione "var"
var bool $flag;
// Le proprietà tipizzate possono avere valori di default
public string $str = "foo";
public ?string $nullableStr = null;
// Tipi applicati a tutte le proprietà in una singola dichiarazione
public float $x, $y;
// equivale a:
public float $x;
public float $y;
}
Il ? anteposto ad un tipo indica che quella proprietà può accettare anche valori null.
Ereditarietà
I tipi delle proprietà sono invarianti. Questo significa che il tipo definito nelle proprietà di una classe, eccetto per quelle private, dovrà necessariamente restare lo stesso anche per le classi che ereditano.
class A {
private bool $a;
public int $b;
public ?int $c;
}
class B extends A {
public string $a; // consentito, A::$a è dichiarata come privata
public ?int $b; // non consentito
public int $c; // non consentito
}
Valori di default
Siamo spesso abituati ad inizializzare le proprietà di una classe con un valore di default. Tale operazione è consentita anche per le proprietà tipizzate, l'unico vincolo è che il tipo del valore assegnato sia compatibile con la dichiarazione.
class Test {
// Valori di default accettati
public bool $a = true;
public int $b = 42;
public float $c = 42.42;
public float $d = 42; // esenzione speciale
public string $e = "str";
public array $f = [1, 2, 3];
public iterable $g = [1, 2, 3];
public ?int $h = null;
public ?object $i = null;
public ?Test $j = null;
// Valori di default non accettati
public object $k;
public Test $l;
// Valori di default inaccettabili
public bool $m = 1;
public int $n = null;
public Test $o = null;
}