Re: Constructor promoted property and default value

From: Date: Mon, 23 Oct 2023 15:16:26 +0000
Subject: Re: Constructor promoted property and default value
References: 1  Groups: php.internals 
Request: Send a blank email to internals+get-121444@lists.php.net to get a copy of this message
On Mon, Oct 23, 2023, at 2:18 PM, Pierre wrote: > Hello internals, > > I stumbled upon this behavior, if I write this: > > ```php > class Foo > { >     public ?string $prop = null; > >     public function __construct(?string $prop = null) >     { >         $this->prop = $prop; >     } > } > > class Bar extends Foo > { >     public function __construct( >         public ?string $bar = null, >     ) {} > } > > // Echoes nothing, but it works as expected. > echo (new Bar())->prop; > ``` > > It works as intended, but if I replace the Foo class using: > > ```php > class Foo > { >     public function __construct( >         public ?string $prop = null, >     ) {} > } > ``` > > It won't work anymore and I have the following error: > > ``` > PHP Warning:  Uncaught Error: Typed property Foo::$prop must not be > accessed before initialization in php shell code:9 > ``` > > If I understand it correctly: >  - in the first case, default value is attached to the object property, > so if I omit its constructor, I have the default, >  - in the second case, default value is attached to the constructor > parameter, and not to the object property, which means that in case the > parent constructor is not called in the Bar class, > $prop remains > initialized. > > It doesn't sound like a bug, but I think that many people would actually > expect otherwise: that the constructor promoted property keep their > default even when constructor is not explicitly called. > > Is there any good reason behind this ? Wouldn't it be best to change > this behavior ? Would it be a risk for backward compatibility (my guess > is "not that much, probably not a all even") ? Where this becomes a problem is readonly properties, since those are not allowed to have default values. (That would make them constants with worse performance.) A solution would need to be able to detect that the parent::__construct() isn't called, and then call it anyway, or at least partially call it. Unfortunately, I can think of many cases where such a call would result in unexpected behavior. It might be possible to resolve, but it's definitely not simple, and it could easily lead to weird behavior. --Larry Garfield

« previous php.internals (#121444) next »