On Fri, Jul 18, 2025, at 17:25, Tim Düsterhus wrote: > Hi > > On 7/14/25 15:38, Larry Garfield wrote: > > Thanks, Ilija. You expressed my concerns as well. And yes, in practice, > > readonly classes over-reaching is the main use case; if you're marking > > individual properties readonly, then just don't mark the one that has a > > hook on it (use aviz if needed) and there's no issue. > > A readonly class is not just a convenience shortcut to mark each > individual property as readonly. It has important semantics of its own, > because it forces child classes to also be readonly. And even for final > classes it communicates to the user that "I won't be adding non-readonly > properties to the class".
Wasn’t that the entire point of readonly classes? Because it was painful to write readonly for every property. Then if a property is readonly, the inherited property is also readonly, so, by extension: a class extending a readonly class is also readonly. There’s no “communication” here; just logic. > > Marking a class as readonly must therefore be a deliberate decision, > since it affects the public API of your class and in turn also user > expectations. Not really. I can remove the readonly designation and manually mark every property as readonly. The behavior of the class doesn’t magically change. Or, at least, I hope it doesn’t. > > > Perhaps we're thinking about this the wrong way, though? So far we've > > talked as though readonly makes the property write-once. But... what if we > > think of it as applying to the field, aka the backing value? > > I think of readonly from the view of the public API surface of an > object. The property hooks RFC was very explicit in that property hooks > are intended to be “transparent to the user” and can be added without > breaking the public API. In other words: Whether or not a property is > implemented using a hook should be considered an implementation detail > and as a user of a class I do not care whether there is a backing value > or not. > > > So readonly doesn't limit calling the get hook, or even the set hook, > > multiple times. Only writing to the actual value in the object table. > > That gives the exact same set of guarantees that a getX()/setX() method > > would give. The methods can be called any number of times, but the stored > > value can only be written once. > > As a user of a class the "backing table" is mostly inaccessible to me > when interacting with objects. It's only exposed via var_dump() and > serialize(), the former of which is a debug functionality and the output > of latter not something I must touch. > > > It would not guarantee $foo->bar === $foo->bar in all cases (though that > > would likely hold in the 99% case in practice), but then, $foo->getBar() > > === $foo->getBar() has never been guaranteed either. > > Properties and methods are something different. For methods there a > reasonable expectation that *behavior* is associated with them, for > properties there is not. Unless I missed something. Hooks are fancy methods? There is nothing intrinsic about object properties. There is nothing that says two calls to the same property’s getters are going to result in the same values. There is asynchronous php, declare ticks, etc. especially in the case of globals, there is no guarantee you even have the same object. At the end of the day, it is up to the programmer building that system / program to provide those guarantees— not the language. > > A 99% case is not sufficient for me to rely on when there's explicit > communication by the class author that I may rely on properties not > suddenly changing. > > Best regards > Tim Düsterhus > — Rob