> On 6 Aug 2022, at 00:08, Larry Garfield <la...@garfieldtech.com> wrote:
> 
> Ilija Tovilo and I are happy to present the first new RFC for PHP 8.3: 
> Asymmetric Visibility.
> 
> https://wiki.php.net/rfc/asymmetric-visibility
> 
> Details are in the RFC, but it's largely a copy of Swift's support for the 
> same.
> 
> -- 
>  Larry Garfield
>  la...@garfieldtech.com
> 
> -- 
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
> 

Hi Larry,


I like most of this, but I have one disagreement.

Can you expand a bit more on the reasoning for restricting the ability to 
combine __set() here?

The RFC states that it’s to keep consistency with `readonly`, because __set on 
a readonly property that’s initialised throws an error - but isn’t that because 
of the nature of it being readonly, rather than because of the visibility 
rules? The error given is "Cannot modify readonly property” thrown from within 
the __set() method, not "Cannot access protected property” thrown from the 
outside calling context, when the __set() method is not implemented.

If I set a property to readonly I would expect it to not be settable after 
initialisation, regardless of visibility, whether it’s via direct access or via 
__set, etc. (i.e. what readonly does now)

But if I set a property to `public private(set)` for example, I would 
**expect** that the __set method on that class (or in the hierarchy if using 
protected(set)) would be called when setting it from an inaccessible context, 
just as it would be called when setting a regular protected property.


It seems very unintuitive to me, that the first example here would work, but 
that the second would not work:

class Foo {
    
    protected readonly int $bar;
    
    public function __set(string $name, mixed $value): void {
        $this->{$name} = $value;
    }
}

$a = new Foo;
$a->bar = 1;


class Bar {
    
    public protected(set) int $baz;
    
    public function __set(string $name, mixed $value): void {
        $this->{$name} = $value;
    }
}

$b = new Bar;
$b->baz = 1;



Cheers

Stephen 


Reply via email to