# Traits and redeclaring static properties

- Thread: https://externals.io/message/119809
- Original archive: https://news-web.php.net/php.internals/119809
- Started by Ilija Tovilo on 2023-03-31T13:07:51+00:00
- Messages: 2
- RFC: Traits (Implemented (PHP 5.4)) — https://externals.io/rfc/horizontalreuse.md
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #119809 — Ilija Tovilo — 2023-03-31T13:07:51+00:00

URL: https://externals.io/message/119809#119809

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

https://3v4l.org/Dll1m
```
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"
```

https://3v4l.org/SClLn
```
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

---

## #119810 — Larry Garfield — 2023-03-31T13:12:11+00:00

URL: https://externals.io/message/119809#119810 · In reply to: #119809

> 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
>
> https://3v4l.org/Dll1m
> ```
> 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"
> ```
>
> https://3v4l.org/SClLn
> ```
> 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
> > […]
>
> 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

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
