Re: Primary Constructors

From: Date: Mon, 22 Jun 2026 15:15:29 +0000
Subject: Re: Primary Constructors
References: 1  Groups: php.internals 
Request: Send a blank email to internals+get-131456@lists.php.net to get a copy of this message
On Wed, Jun 17, 2026, at 4:32 PM, Rob Landers wrote: > Hello internals, > > I was reminded of my records RFC today, and one of the features of the > RFC was "short constructors" generally called "primary constructors" in > C#/Kotlin. > > They would look like this: > > class Point(public int $x, int $id = 0) extends Base($id); > > Which is just sugar for this: > > class Point extends Base { > public function __construct(public int $x, int $id = 0) { > parent::__construct($id); > } > } > > or this: > > class Point extends Base { > public int $x; > public function __construct(int $x, int $id = 0) { > $this->x = $x; > parent::__construct($id); > } > } > > A class with a primary constructor *may not* have a defined > __construct function. Any special initialization must be done > with > hooks: > > class Temperature( > public float $celsius { > set { > if ($value < -273.15) { > throw new ValueError('below absolute zero'); > } > $this->celsius = $value; > } > } > ) {} > > new Temperature(20.0); // ok > new Temperature(-300.0); // ValueError: below absolute zero > > I'm sending this email to the list to gather additional feedback before > pursuing a formal RFC proposal. > > — Rob I would support this, and I agree that KISS is the best way to go for now. I don't know if it makes sense to include in the initial design, but for reference here's how Kotlin handles construction: class Person(val name: String, val age: Int) { // Primary constructor, equivalent to promotion and what's proposed here. init { // Argument-less code block/method that runs after the primary constructor is assigned. // This could be useful to include for more complex cases, like where hooks are useful. } // Secondary constructor constructor(name: String): this(name, 0) { // This constructor gets called first, but is forced to call the primary constructor syntactically. // Then it can do other stuff if it wants. } } cf: https://kotlinlang.org/docs/classes.html#constructors-and-initializer-blocks I don't think we should include the "secondary constructor calls primary constructor and you have to make sure it works" logic. However, I do think we can/should consider an init block. Though how that interacts with inheritance I'm not sure yet. Putting non-trivial property hooks inside a constructor promotion is already strongly discouraged, and I would recommend continuing to discourage them even with this syntax. However, that does raise a concern that we would really benefit from some way to allow property hooks to be defined "on their own" on a property, AND link the property to a promoted constructor argument. I'm not sure off hand how we would do that, and it's somewhat tangential to this syntax, but I am pointing it out for completeness. As for the readonly/hooks incompatibility, honestly, I don't care. :-) Readonly is frequently problematic, Internals has already rejected making readonly and hooks compatible, and protected(set) gets you almost the same rules with none of the conflicts. So I'm good there. --Larry Garfield

« previous php.internals (#131456) next »