> On 14 Nov 2022, at 03:08, Larry Garfield <la...@garfieldtech.com> wrote:
> 
> Hi folks.  Ilija is nearly done with the implementation for asymmetric 
> visibility and flushing out edge cases, but we've run into one design 
> question we'd like feedback on.
> 
> There's two design decisions we've made at this point, both of which we think 
> are logical and reasonable:
> 
> 1. If specified, the set visibility must be tighter than the get visibility.  
> So `protected protected(set)` and `protected public(set)` are not permitted, 
> for instance.
> 
> 2. `readonly` is a "write once" flag that may be combined with asymmetric 
> visibility.  If no set visibility is specified, `readoly` implies 
> `private(set)`, but a different set visibility may also be provided.
> 
> These are both reasonable rules.  However, it creates a conflict.  
> Specifically, in the following cases:
> 
> public public(set) readonly string $foo
> 
> protected protected(set) readonly string $foo
> 
> These would be the only way to have a non-private-set readonly property.  
> While the first is in practice quite unlikely, the second has valid use 
> cases.  (In particular, a base class that provides properties expected to be 
> set by a child constructor, and then used by a method in the parent class.)  
> However, it would not be allowed under the rules above.  Working around it 
> would require specifying `public protected(set) readonly...`, which means 
> exposing a property that likely should not be exposed.
> 
> That creates an odd situation where readonly and asymmetric visibility may 
> only be combined "sometimes."  That is not deesireable.  The only way to 
> combine them in their current form is to allow `protected protected(set)` 
> only if readonly is in use, which is excessively complicated both to 
> implement and to explain/document/use.
> 
> We see two possible ways to resolve this conflict:
> 
> 1. Relax the set-is-tighter restriction.  That would allow `protected 
> protected(set)` etc. on any property.  It wouldn't be particularly useful 
> unless readonly is being used, but it would be syntactically legal and behave 
> as you'd expect.  We could still disallow "set is more permissive" 
> combinations (eg, `private public(set)`), as those have no apparent use case.
> 
> 2. Disallow readonly and asymmetric visibility being combined, because 
> readonly already has a hard-coded implied asymmetric visibility.  This option 
> removes some potential use cases (they would most likely drop the readonly), 
> but has the upside that it's easier to re-allow at some point in the future.
> 
> 3. Some other brilliant idea we've not thought of.
> 
> 
> Both are viable approaches with pros and cons.  We're split on which way to 
> go with this, so we throw it out to the group for feedback.  Which approach 
> would you favor, or do you have some other brilliant idea to square this 
> circle?
> 
> 
> -- 
>  Larry Garfield
>  la...@garfieldtech.com
> 
> -- 
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
> 

Hi Larry,

I asked for some clarification / further thought about the magic 
getters/setters interaction of this RFC back when you announced it, and never 
heard much besides saying that you’re working on a consolidated response to the 
feedback, but I’ve not seen anything regarding what I’d asked about, and the 
RFC still seems to have the (IMO) confusing and inconsistent magic 
getters/setters interaction described.


As I understand it, you’re suggesting that a property declared as `public 
protected(set)` would never trigger __set().


While I understand that this is meant to “keep consistency with readonly”, I 
would imagine people would want to use native asymmetric visibility on objects 
that currently have protected (or private) properties that are accessed via 
magic getters and setters. I think it would be a natural assumption that 
asymmetric visibility would allow the user to remove the often boilerplate 
__get method, while maintaining the ability to have checks/other logic beyond 
simple type checks when a property is being set. Having the association of a 
*set* action tied to the *get* visibility is very unintuitive to me.

The impact of this “same” limitation on readonly properties is IMO greatly 
reduced, because of the nature of something being readonly. The ability to run 
some logic when writing to a property that’s otherwise readable is surely a 
concept that’s very common and easy to understand, it’s literally the next 
example after (1) “readonly” and (2)  “asymmetric visibility” in Nikita’s 
original property accessors RFC.

The stated reason (on both this and the readonly RFC) for not allowing __set() 
is "to avoid surprising behaviour”. To me, having a field marked as `public 
protected(set)` then not call __set() when setting a property from outside the 
class **is** the surprising behaviour.



Cheers

Stephen





Reply via email to