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. Ad esempio:
$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;
}