PHP 8.1 přichází se zajímavou novinkou: readonly členské proměnné:
Začneme rovnou příkladem použití:
class Test
{
public readonly string $prop;
public function setProp(string $prop): void
{
$this->prop = $prop; // legal initialization
}
}
$obj = new Test;
$obj->setProp('abc');
echo $obj->prop; // legal read
$obj->prop = 'foo'; // throws exception: Cannot modify readonly property Test::$prop
Tedy jednou inicializovaná proměnná už nemůže být přepsána jinou hodnotou.
Scope
Překvapivě ale přiřazení do $obj->prop
vyhodí výjimku
i v případě, že proměnná inicializovaná není:
$obj = new Test;
$obj->prop = 'foo';
// throws exception too: Cannot initialize readonly property Test::$prop from global scope
Dokonce i tohle vyhodí výjimku:
class Child extends Test
{
public function setProp(): void
{
$this->prop = 'hello';
// throws exception: Cannot initialize readonly property Test::$prop from scope Child
}
}
$obj = new Child;
$obj->setProp();
Do readonly proměnné prostě nelze zapsat odjinud než ze třídy, která ji definovala. Zvláštní.
Neměnnost
To, že nelze měnit obsah readonly proměnných, ještě neznamená, že data tam zapsané jsou neměnné. Pokud do takové proměnné zapíšeme objekt, můžeme nadále měnit jeho vnitřní proměnné. Objekt se nestane immutable.
To stejné platí pro pole. Byť tam je chování trošku odlišné. Změna prvků v poli se považuje za změnu celého pole a tedy jako taková je v readonly proměnné nepřípustná. Ale pokud pole obsahuje prvek, který je referencí, změna jeho obsahu se za změnu celého pole nepovažuje a tedy k ní může v readonly prvku docházet. Což je nicméně standardní chování PHP odjakživa.
Jinými slovy tohle lze:
class Test
{
public readonly array $prop;
public function setProp(): void
{
$item = 'foo';
$this->prop = [1, &$item, 2];
var_dump($this->prop); // [1, 'foo', 2]
$item = 'bar'; // legal
var_dump($this->prop); // [1, 'bar', 2]
}
}
Ale tohle nelze:
class Test
{
public readonly array $prop;
public function setProp(): void
{
$this->prop = ['a', 'b'];
$this->prop[1] = 'c'; // throws exception!
}
}
Typ
Protože readonly proměnné využívají stavu ‚uninitialized‘, který existuje u proměnných s definovaným typem, je možné readonly uvádět jen společně s datovým typem.
Komentáře
Adam #1
Díky za článek, pomohl nyní na jednom webu.
Napište komentář