On Thu, Feb 20, 2020, at 3:06 AM, Nikita Popov wrote: > 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
> From Máté Kocsis <kocsismat...@gmail.com> wrote: > No, it doesn't work, and it seems to be an unrelated feature for me. As far > as I understand your > example, it's the topic of the "Constant expressions" RFC. > > I believe the behaviour proposed by my RFC would be still useful in many > cases where one wants > to be sure that no unexpected modifications can happen with a property. My > use-cases > would mainly include objects storing different kind of data: events, value > objects, data transfer objects. Yeah, I'm definitely thinking in relation to the earlier discussion, since I think they're all inter-related. (This, property accessors, and constant expressions.) As Nikita notes above, a read-only property with a default value is... basically a constant already. So that's not really useful. For defined-later readonly properties, I'm not sure how the earlier point about reading an unintialized property isn't valid. Currently: class Foo { public string $bar; } $f = new Foo(); print $f->bar; // this throws a TypeError. I would expect the exact same behavior if $bar were marked readonly/locked/whatever. Are you saying that's not the case? I do think it's fair to bring in the property accessor discussion here, as property accessors would allow for the same net functionality as this property as a special case, albeit with likely more syntax. AFAIR the issue with them before wasn't that people opposed the idea, just the performance impact. If we could address the performance impact, that would give us much more functionality-for-the-buck, including an equivalent of read-only properties including potentially lazy initialization. Or derive-on-demand behavior would also be a big increase in functionality. It's not that I don't see a value to this RFC; I actually have a few places in my own code where I could use it. It's that I see it as being of fairly narrow use, so I'm trying to figure out how to increase it so that the net-win is worth it. --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php