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".

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.

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.

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

Reply via email to