Na navigaci | Klávesové zkratky

Readonly Variables in PHP 8.1 Will Surprise You

PHP 8.1 introduces an interesting feature: readonly member variables:

Let's start with an example of how to use 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

Once initialized, a variable cannot be overwritten with another value.

Scope

Interestingly, attempting to assign a value to $obj->prop will also throw an exception even if the variable hasn't been initialized:

$obj = new Test;
$obj->prop = 'foo';
// throws exception too: Cannot initialize readonly property Test::$prop from global scope

This will even throw an exception:

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();

A readonly variable simply cannot be written from anywhere other than the class that defined it. Quite peculiar.

Immutability

The fact that the content of readonly variables cannot be changed doesn't mean the data written to them is immutable. If an object is written to such a variable, its internal variables can still be modified. The object does not become immutable.

The same applies to arrays. Although the behavior is slightly different here. Changing elements in the array is considered a change to the entire array and as such is impermissible in a readonly variable. However, if the array contains an element that is a reference, changing its content is not considered a change to the entire array and thus can occur in a readonly element. This, however, is standard PHP behavior as always.

In other words, this is possible:

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

But this is not possible:

class Test
{
	public readonly array $prop;

	public function setProp(): void
	{
		$this->prop = ['a', 'b'];
		$this->prop[1] = 'c'; // throws exception!
	}
}

Type

Since readonly variables utilize the ‘uninitialized’ state, which exists for variables with a defined type, it is only possible to declare a variable as readonly in conjunction with a data type.

You might be interested in

Leave a comment

Text of the comment
Contact

(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í.