On Wed, Sep 19, 2018 at 1:06 PM Rasmus Schultz <ras...@mindplay.dk> wrote: > > On Wed, Sep 19, 2018 at 7:43 PM Rowan Collins <rowan.coll...@gmail.com> wrote: > > > I agree that this is a hard problem, but I don't agree that this decision > > is being made "for now". If we allow "non-nullable but uninitialized" > > properties now, it will be extremely hard to change their behaviour in > > future. > > I'm with Rowan on this one. > > This concept of "uninitialized" frankly seems like an allowance for > people who insist on writing poor code. > > Nulls are bad, and "unintialized" is just another kind of "null" with > a built-in run-time type-check that executes on read - too late. > > The first example given is just bad: > > class Point { > public float $x, $y; > > private function __construct() {} > > public static function fromEuclidean(float $x, float $y) { > $point = new Point; > $point->x = $x; > $point->y = $y; > return $point; > } > } > > You define two invariants: $x and $y must be floats - and then proceed > to break those constraints in the constructor? > > Wrong. The RFC itself accurately states that "this code can be > rewritten to indirect through __construct() instead" - as shown in the > previous example. > > Now why would you deliberately open the fences and knowingly invite > people to write poor code like this? > > As for the second example: > > class Point { > public float $x, $y; > > public function __construct(float $x, float $y) { > $this->doSomething(); > $this->x = $x; > $this->y = $y; > } > } > > If doSomething() attempts to read an uninitialized property while the > constructor is still executing, throwing a helpful "uninitialized" > error is fine. > > But, in my opinion, once the constructor has executed, the invariants > as declared by the class itself must be satisfied. > > If there's one meaningful use-case for allowing objects in a > partially-initialized state, it's during > hydration/unserialization/reflection scenarios, maybe - but in those > cases, you're willfully bypassing the constructor; it's not the > everyday 95% use-case and some risk is acceptable here, you'll get > around it with tests. But nobody wants to write tests all day to see > if any classes contain "unininitialized" properties - that misses half > the whole point of being able to declare those types in the first > place, e.g. makes type-hinted private/protected properties totally > unreliable. > > Once this is in a release, it'll be unfixable, and in my opinion will > likely go down in history as another one of those little things we > wish we could go back in time and fix :-/ > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php
PHP permits skipping constructors. The code may not work if you do so, but it's the state of how things are. Validating after a constructor call will not catch all issues while requiring a constructor, whereas I think this code should be allowed: class User { public int $id; public string $preferred_name; public string $username; } I doubt we will come to a resolution -- these points were already pointed out in the discussion phase. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php