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; } Regards, -- Rowan Tommins [IMSoP]