On Mon, Feb 24, 2020, at 7:55 AM, Rowan Tommins wrote: > On Fri, 21 Feb 2020 at 23:18, Larry Garfield <la...@garfieldtech.com> wrote: > > > 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. > > > > > As with typed properties, I wonder if there's a way we can introduce a new > initialisation sequence for objects, so that there's a specific point where > the object is considered "fully constructed" after new or clone. > > A couple of brainstormed ideas, with plenty of downsides I'm sure: > > An explicit finalise() function or keyword > > public function withFoo($foo) { > $inst = clone $this; > // all readonly properties are initially "unlocked" > $inst->foo = $foo; > // now lock them, perhaps also checking that no typed properties are > left uninitialised > finalise($inst); // or finalise $inst; > return $inst; > } > > A special code block: > > public function withFoo($foo) { > $inst = clone $this { > // all properties are "unlocked" within this special block > $inst->foo = $foo; > }; > // from here onwards, readonly properties can't be written to > return $inst; > } > > Perhaps could also be used with constructors: > > public function createFromOtherThing(OtherThing $other) { > $inst = new static('some parameter') { > // readonly properties can be written in the constructor, or > within this block > $inst->foo = $other->getFoo(); > }; > // object is "finalised" when the block ends > return $inst; > }
If the way to resolve this question is a special "unlocked" mode, I would definitely favor the explicit code block. That way it's self-closing and you can't forget to do so. (Murphy's Law: If you rely on developers remembering to do X to keep code safe, they will promptly forget to do X.) Also, FTR, any approach that forces developers to write a 9 parameter constructor over and over is one I can never get behind, doubly so for something that is currently only a single line. This isn't a case of "pain tells you what not to do"; a value object having a lot of internal properties is a completely valid use case, and "but composition" is not an answer. --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php