On Tue, Nov 26, 2024, at 3:42 PM, Jonathan Vollebregt wrote: > On 11/26/24 9:35 PM, Larry Garfield wrote: >> Thinking aloud, my expectation would be that it behaves similarly to how >> final static methods would behave. Which appears to be a syntax error: >> https://3v4l.org/j8mp0#v8.4.1 >> >> So, shouldn't properties do the same? > > Without final you can still override both private static properties and > private static methods: https://3v4l.org/MS73Y#v8.4.1 > > When explicitly declared final, static properties do result in a syntax > error: https://3v4l.org/fqI8v#v8.4.1 > > Re-reading the logic in the original aviz RFC makes me think implicit > final here is unnecessary. All static properties are "Shadowed" like > private properties (even when they're public) so there's no conflicting > behavior. > > The two behaviors described as conflicting in the aviz RFC are decided > explicitly in the context of static properties, by the caller accessing > it with `self::` or `static::`. Not by a combination of the visibility > and child classes. > > Consider this example: > > ``` > class A { > private(set) static int $a = 1; > > public static function test(int $val) { > static::$a = $val; > } > } > > class B extends A { > private(set) static int $a = 2; > } > > B::test(3) > ``` > > Yes this would produce a fatal error, but doing this with just `private > static` does the same in current PHP: https://3v4l.org/Y6lZ7#v8.4.1 > > You might want to discuss banning use of `static::` on private statics, > but that's a big BC break. > > Since static properties do still have to have equal or wider visibility > when extending I'd say using `static::$prop` on a property you know is > private is a known risk and remove the implicit final. > > - Jonathan
Hi folks. Finally getting back to this thread. Ilija and I have discussed it, and it seems to us that the consistency of implicit-final-on-private-set (on both object and static properties) is more valuable than maximal flexibility, especially as we're dealing with a rare use case to begin with. Specifically, `static::$prop` is still expected to behave the same as the parent class's $prop. Eg, its type can't change, its visibility cannot be narrowed, etc. So a private(set) parent $prop would violate that expectation, the same way it would for a dynamic property. Introducing another subtle difference between self:: and static:: doesn't seem like a good thing for DX. Additionally, if we find in the future that it really would be better to not have the implicit final and allow people to "opt in" via self::vs static::, it's less of a BC break to remove the implicit final in the future than to try and introduce it. For that reason, we are going to keep static properties consistent with object properties in this regard. --Larry Garfield