On Thu, Feb 20, 2020 at 1:27 AM Matthew Brown <matthewmatt...@gmail.com>
wrote:

> Someone recently requested something similar for a PHP static analysis tool
> I wrote (https://psalm.dev/r/f75997a263), though that version only allows
> lazy initialisation inside the class in which a given property is declared.
>
> Personally I don't like either approach – I think per-property getters and
> setters would be a more appropriate venue for this functionality, something
> like:
>
> property int $s {
>     public get;
>     private set;
> }
>
> This pattern could also be extended to support per-property getter and
> setter methods.
>

While I certainly like the idea of per-property getters/setters, I think
that both of these have their place. This RFC proposes readonly properties,
that can be initialized once, and then never modified again, even within
the same class. Getters/setters only provide the possibility of having
asymmetric visibility: They prevent modifying the property from outside the
class, but it can still be modified inside the class. In that, readonly
properties offer a stronger guarantee.

Of course, that does leave the question of how often you need one or the
other. Maybe just the asymmetric visibility is sufficient for most
practical purposes, in which case it may not be worthwhile to introduce
readonly properties as a separate feature.

Two comments on the specifics of the RFC:

The RFC allows specifying a default value for readonly properties. However,
a property for which a default value has been specified will always have
that value, as it cannot be overwritten in the constructor. If you write
"public readonly int $foo = 42", then $object->foo is *always* going to be
42. I'm not sure what that would ever be useful for, and it seems like
something that is bound to be confusing. Maybe it would make more sense to
forbid readonly properties with default values? (That way, the rule that
readonly properties have to be typed falls out naturally as well -- untyped
properties always have a default.)

Regarding the keyword choice, I think you can drop "sealed" from the list,
as it is an established term that affects inheritance, not mutability. Of
the choices you present, "immutable", "readonly" and "writeonce" seem like
the most viable candidates. "writeonce", while the one that is most
technically accurate, is also *unnecessarily* technically accurate and not
intuitive. From the perspective of an API consumer, I think that "readonly"
is the most accurate description of how they are supposed to interact with
the property. The API contract you want to expose is that they can only
read from the property, not write to it. Calling it "writeonce" would be
quite confusing in that context, because the API consumer is never expected
to write to the property. In the majority of cases you will be providing
fully initialized objects, in which case they are indeed readonly for the
consumer -- the details of the write-once property are only relevant in
special cases like ReflectionClass::newObjectWithoutConstructor() for
serialization libraries, or lazy initialization like in Marco's
ProxyManager.

Regards,
Nikita


> On Wed, 19 Feb 2020 at 12:06, Máté Kocsis <kocsismat...@gmail.com> wrote:
>
> > Hi Internals,
> >
> > I'd like to move my RFC forward to the discussion phase:
> > https://wiki.php.net/rfc/write_once_properties
> >
> > In short, I propose to add support for a new property modifier that would
> > allow properties to be initialized, but not modified afterwards.
> >
> > Cheers,
> > Máté Kocsis
> >
>

Reply via email to