Skip to content

Commit b0a042d

Browse files
committed
Add support for final properties
1 parent 373a6d8 commit b0a042d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1370
-38
lines changed

Zend/tests/errmsg_038.phpt

Lines changed: 0 additions & 13 deletions
This file was deleted.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
--TEST--
2+
Test that ArrayAccess works for final properties as expected
3+
--FILE--
4+
<?php
5+
6+
class Foo implements ArrayAccess
7+
{
8+
final private string $property1;
9+
final private string $property2 = "";
10+
11+
function offsetExists($offset)
12+
{
13+
return isset($this->$offset);
14+
}
15+
16+
function offsetGet($offset)
17+
{
18+
return $this->$offset ?? null;
19+
}
20+
21+
function offsetSet($offset, $value)
22+
{
23+
$this->$offset = $value;
24+
}
25+
26+
function offsetUnset($offset){
27+
unset($this->$offset);
28+
}
29+
}
30+
31+
$foo = new Foo();
32+
33+
$foo["property1"] = "foo";
34+
35+
try {
36+
$foo["property1"] = "foo";
37+
} catch (Error $exception) {
38+
echo $exception->getMessage() . "\n";
39+
}
40+
41+
try {
42+
$foo["property2"] = "foo";
43+
} catch (Error $exception) {
44+
echo $exception->getMessage() . "\n";
45+
}
46+
47+
$foo["property3"] = "foo";
48+
49+
?>
50+
--EXPECT--
51+
Cannot modify final property Foo::$property1 after initialization
52+
Cannot modify final property Foo::$property2 after initialization
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
Test that final properties can be used with key() and current(), but not with next()
3+
--XFAIL--
4+
Incorrect error message
5+
--FILE--
6+
<?php
7+
8+
class Foo
9+
{
10+
final public array $property1 = ["foo", "bar", "baz"];
11+
}
12+
13+
$foo = new Foo();
14+
15+
var_dump(current($foo->property1));
16+
var_dump(key($foo->property1));
17+
18+
try {
19+
next($foo->property1);
20+
} catch (Error $exception) {
21+
echo $exception->getMessage() . "\n";
22+
}
23+
24+
?>
25+
--EXPECT--
26+
string(3) "foo"
27+
int(0)
28+
Cannot modify final property Foo::$property1 after initialization
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
--TEST--
2+
Test that declared final properties can't be accessed by reference
3+
--FILE--
4+
<?php
5+
6+
class Foo
7+
{
8+
final public int $property1;
9+
final public int $property2 = 2;
10+
11+
public function __construct()
12+
{
13+
$this->property1 = 1;
14+
}
15+
16+
public function &getProperty2(): int
17+
{
18+
return $this->property2;
19+
}
20+
}
21+
22+
$foo = new Foo();
23+
24+
try {
25+
$x = &$foo->property1;
26+
} catch (Error $exception) {
27+
echo $exception->getMessage() . "\n";
28+
}
29+
30+
try {
31+
$foo->getProperty2();
32+
} catch (Error $exception) {
33+
echo $exception->getMessage() . "\n";
34+
}
35+
36+
?>
37+
--EXPECT--
38+
Cannot acquire reference on final property Foo::$property1
39+
Cannot acquire reference on final property Foo::$property2
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
--TEST--
2+
Test that final properties can't be incremented/decremented
3+
--FILE--
4+
<?php
5+
6+
class Foo
7+
{
8+
final public int $property1;
9+
final public int $property2;
10+
}
11+
12+
$foo = new Foo();
13+
14+
try {
15+
++$foo->property1;
16+
} catch (Error $exception) {
17+
echo $exception->getMessage() . "\n";
18+
}
19+
20+
try {
21+
$foo->property1++;
22+
} catch (Error $exception) {
23+
echo $exception->getMessage() . "\n";
24+
}
25+
26+
$foo->property1 = 1;
27+
$foo->property2 = 2;
28+
29+
try {
30+
++$foo->property1;
31+
} catch (Error $exception) {
32+
echo $exception->getMessage() . "\n";
33+
}
34+
35+
try {
36+
++$foo->property2;
37+
} catch (Error $exception) {
38+
echo $exception->getMessage() . "\n";
39+
}
40+
41+
try {
42+
$foo->property1++;
43+
} catch (Error $exception) {
44+
echo $exception->getMessage() . "\n";
45+
}
46+
47+
try {
48+
$foo->property2++;
49+
} catch (Error $exception) {
50+
echo $exception->getMessage() . "\n";
51+
}
52+
53+
var_dump($foo->property1);
54+
var_dump($foo->property2);
55+
56+
try {
57+
--$foo->property1;
58+
} catch (Error $exception) {
59+
echo $exception->getMessage() . "\n";
60+
}
61+
62+
try {
63+
--$foo->property2;
64+
} catch (Error $exception) {
65+
echo $exception->getMessage() . "\n";
66+
}
67+
68+
try {
69+
$foo->property1--;
70+
} catch (Error $exception) {
71+
echo $exception->getMessage() . "\n";
72+
}
73+
74+
try {
75+
$foo->property2--;
76+
} catch (Error $exception) {
77+
echo $exception->getMessage() . "\n";
78+
}
79+
80+
var_dump($foo->property1);
81+
var_dump($foo->property2);
82+
83+
?>
84+
--EXPECT--
85+
Typed property Foo::$property1 must not be accessed before initialization
86+
Typed property Foo::$property1 must not be accessed before initialization
87+
Cannot increment final property Foo::$property1
88+
Cannot increment final property Foo::$property2
89+
Cannot increment final property Foo::$property1
90+
Cannot increment final property Foo::$property2
91+
int(1)
92+
int(2)
93+
Cannot decrement final property Foo::$property1
94+
Cannot decrement final property Foo::$property2
95+
Cannot decrement final property Foo::$property1
96+
Cannot decrement final property Foo::$property2
97+
int(1)
98+
int(2)
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
--TEST--
2+
Test that final properties can't be incremented/decremented by reference
3+
--FILE--
4+
<?php
5+
6+
class Foo
7+
{
8+
final public int $property1;
9+
final public int $property2 = 2;
10+
11+
public function __construct()
12+
{
13+
$this->property1 = 1;
14+
}
15+
}
16+
17+
$foo = new Foo();
18+
foreach ($foo as &$property) {
19+
try {
20+
++$property;
21+
} catch (Error $exception) {
22+
echo $exception->getMessage() . "\n";
23+
}
24+
}
25+
26+
var_dump($foo->property1);
27+
var_dump($foo->property2);
28+
29+
$foo = new Foo();
30+
foreach ($foo as &$property) {
31+
try {
32+
$property++;
33+
} catch (Error $exception) {
34+
echo $exception->getMessage() . "\n";
35+
}
36+
}
37+
38+
var_dump($foo->property1);
39+
var_dump($foo->property2);
40+
41+
foreach ($foo as &$property) {
42+
try {
43+
--$property;
44+
} catch (Error $exception) {
45+
echo $exception->getMessage() . "\n";
46+
}
47+
}
48+
49+
var_dump($foo->property1);
50+
var_dump($foo->property2);
51+
52+
foreach ($foo as &$property) {
53+
try {
54+
$property--;
55+
} catch (Error $exception) {
56+
echo $exception->getMessage() . "\n";
57+
}
58+
}
59+
60+
var_dump($foo->property1);
61+
var_dump($foo->property2);
62+
63+
?>
64+
--EXPECT--
65+
Cannot increment a reference held by final property Foo::$property1
66+
Cannot increment a reference held by final property Foo::$property2
67+
int(1)
68+
int(2)
69+
Cannot increment a reference held by final property Foo::$property1
70+
Cannot increment a reference held by final property Foo::$property2
71+
int(1)
72+
int(2)
73+
Cannot decrement a reference held by final property Foo::$property1
74+
Cannot decrement a reference held by final property Foo::$property2
75+
int(1)
76+
int(2)
77+
Cannot decrement a reference held by final property Foo::$property1
78+
Cannot decrement a reference held by final property Foo::$property2
79+
int(1)
80+
int(2)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Test that final array properties can be iterated
3+
--FILE--
4+
<?php
5+
6+
class Foo
7+
{
8+
final public array $property1 = ["foo", "bar", "baz"];
9+
}
10+
11+
$foo = new Foo();
12+
13+
foreach ($foo->property1 as $key => $value) {
14+
var_dump("$key => $value");
15+
}
16+
17+
?>
18+
--EXPECT--
19+
string(8) "0 => foo"
20+
string(8) "1 => bar"
21+
string(8) "2 => baz"
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
--TEST--
2+
Test that the __get() magic method works when reading from a final property
3+
--FILE--
4+
<?php
5+
6+
class Foo
7+
{
8+
final private array $properties = [
9+
"property1" => "foo",
10+
"property2" => null,
11+
];
12+
13+
public function __isset($name): bool
14+
{
15+
return isset($this->properties[$name]);
16+
}
17+
18+
public function __get($name)
19+
{
20+
return $this->properties[$name] ?? null;
21+
}
22+
}
23+
24+
$foo = new Foo();
25+
26+
var_dump(isset($foo->property1));
27+
var_dump($foo->property1);
28+
29+
var_dump(isset($foo->property2));
30+
var_dump($foo->property2);
31+
32+
var_dump(isset($foo->property3));
33+
var_dump($foo->property3);
34+
35+
?>
36+
--EXPECT--
37+
bool(true)
38+
string(3) "foo"
39+
bool(false)
40+
NULL
41+
bool(false)
42+
NULL

0 commit comments

Comments
 (0)