Hi everyone
A few days ago we received a bug report about an inconsistency with
traits and static properties.
https://github.com/php/php-src/issues/10935
class A {
static $test;
}
class B extends A {
static $test;
}
A::$test = 'A';
B::$test = 'B';
var_dump(A::$test, B::$test);
// string(1) "A"
// string(1) "B"
trait Foo {
static $test;
}
class A {
use Foo;
}
class B extends A {
use Foo;
}
A::$test = 'A';
B::$test = 'B';
var_dump(A::$test, B::$test);
// string(1) "B"
// string(1) "B"
To summarize, a trait does not add a property to a class that has
already inherited the same property from its parent. This makes sense
for non-static properties, as redeclaring the property essentially has
no effect. For static properties, however, there's a semantic
difference in that redeclaring a static property creates a new slot in
the current class that is separate from the parent's static property
slot.
This was never explicitly specified by the traits RFC. However, this
sentence hints at the fact that the two examples above should behave
equivalently.
https://wiki.php.net/rfc/horizontalreuse
It is almost like a language supported and failsafe copy'n'paste mechanism to build classes.
I created a PR to align the behavior of the two examples. It targets
the master branch to avoid any potential backwards incompatibility in
a patch.
https://github.com/php/php-src/pull/10937
Please let me know if there are any concerns about this change.
Ilija
Hi everyone
A few days ago we received a bug report about an inconsistency with
traits and static properties.https://github.com/php/php-src/issues/10935
class A { static $test; } class B extends A { static $test; } A::$test = 'A'; B::$test = 'B'; var_dump(A::$test, B::$test); // string(1) "A" // string(1) "B"
trait Foo { static $test; } class A { use Foo; } class B extends A { use Foo; } A::$test = 'A'; B::$test = 'B'; var_dump(A::$test, B::$test); // string(1) "B" // string(1) "B"
To summarize, a trait does not add a property to a class that has
already inherited the same property from its parent. This makes sense
for non-static properties, as redeclaring the property essentially has
no effect. For static properties, however, there's a semantic
difference in that redeclaring a static property creates a new slot in
the current class that is separate from the parent's static property
slot.This was never explicitly specified by the traits RFC. However, this
sentence hints at the fact that the two examples above should behave
equivalently.https://wiki.php.net/rfc/horizontalreuse
It is almost like a language supported and failsafe copy'n'paste mechanism to build classes.
I created a PR to align the behavior of the two examples. It targets
the master branch to avoid any potential backwards incompatibility in
a patch.
https://github.com/php/php-src/pull/10937Please let me know if there are any concerns about this change.
Ilija
This seems reasonable to me. "Compile time copy and paste" is the mental model we've been training people to have for a decade, so ensuring it actually works that way in corner cases seems like the right move. I don't think I've ever seen code that would have a behavior change as a result.
--Larry Garfield