Re: [RFC] [DISCUSSION] Immutable/final/readonly properties

From: Date: Sun, 23 Feb 2020 08:39:33 +0000
Subject: Re: [RFC] [DISCUSSION] Immutable/final/readonly properties
References: 1 2 3 4 5 6  Groups: php.internals 
Request: Send a blank email to internals+get-108725@lists.php.net to get a copy of this message
> On Feb 21, 2020, at 6:17 PM, Larry Garfield <larry@garfieldtech.com> wrote: > I'm totally on board for better value object support, so that's a good motive for me. > The question I have is whether this is really a good stepping stone in that direction or if it > would lead down a wrong path and lock us into too much TIMTOWTDI (for the Perl fans in the room). > So let's think that through down that path. How would write-once properties lead into properly > immutable value objects? Or do they give us that themselves? > > The biggest challenge for immutable objects, IMO, is evolving them. Eg, > $result->withContentType(...) to use the PSR-7 example. Would we expect people to do it with a > method like that, or would there be some other mechanism? If the properties are public, would we > offer a more syntactic way to modify them directly? > > The with*() method style requires cloning the object. What happens to the locked status of a > set property if the object is cloned? Are they then settable again, or do they come pre-locked? > > Neither of those seem good, now that I think about it. If they come pre-locked, then you > really can't clone, change one property, and return the new one (as is the standard practice > now in that case). If they don't come pre-locked, then the newly created object can have > everything on it changed, once, which creates a loophole. I'm not sure what the right answer > is here. > > My other concern is a public property (the most likely use case) would have to be set in the > constructor. If it's not, then callers cannot rely on it having been set yet if it's set > lazily. And if code inside the class tries to set it lazily, it may already have been set by some > external code (rightly or wrongly) and cause a failure. > > How do we address that? There's absolutely use cases where setting everything in the > constructor ahead of time is what you'd do anyway, but there are plenty where you wouldn't > want to, either, which creates a race condition for who sets it first, or tries to access it before > it gets set, etc. (This is where my repeated questions about lazy initialization come from.) I have struggled to follow this RFC thread fully, so if I am getting something out of context, please note that and I apologize in advance. However, it would see that rules for write once properties to support lazy loading would be rather simple: 1. Write-once properties can only be updated once. 2. Write-once properties can only be updated within the class where they are declared. 3. If you want to update a property from outside the class, create a set_<property>() method to allow it to happen. 4. If you do not want it to be set externally, do not implement a set_<property>() method. 5. If you want it to be implemented externally sometimes but not others, implement guard classes inside the set_<property>() method. I think that addresses all scenarios, no? -Mike

« previous php.internals (#108725) next »