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

Reply via email to