Na navigaci | Klávesové zkratky

Readonly proměnné v PHP 8.1 vás zaskočí

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
	}
}

$test = new Test;
$test->setProp('abc');
echo $test->prop; // legal read
$test->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 $test->prop vyhodí výjimku i v případě, že proměnná inicializovaná není:

$test = new Test;
$test->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 __construct()
	{
		$this->prop = 'hello';
		// throws exception: Cannot initialize readonly property Test::$prop from scope Child
	}
}

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 test(): void
	{
		$item = 'foo';
		$this->prop = [1, &$item, 2];
		dump($this->prop); // [1, 'foo', 2]
		$item = 'bar'; // legal
		dump($this->prop); // [1, 'bar', 2]
	}
}

Ale tohle nelze:

class Test
{
	public readonly array $prop;

	public function test(): 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

  1. Adam #1

    avatar

    Díky za článek, pomohl nyní na jednom webu.

    před rokem | odpovědět

Zanechat komentář

Text komentáře
Kontakt

(kvůli gravataru)



*kurzíva* **tučné** "odkaz":http://example.com /--php phpkod(); \--

phpFashion © 2004, 2024 David Grudl | o blogu

Ukázky zdrojových kódů smíte používat s uvedením autora a URL tohoto webu bez dalších omezení.