コンストラクタに引数を4個渡したい。
class HOGE{
private int $foo;
protected string $bar;
public array $baz;
public DateTime $qux;
/**
* コンストラクタ
* @param int $foo
* @param string $bar
* @param array $baz
* @param DateTime $qux
*/
public function __construct(int $foo, string $bar, array $baz, DateTime $qux){
$this->foo = $foo;
$this->bar = $bar;
$this->baz = $baz;
$this->qux = $qux;
}
}
毎回こんなの書くのはつらみがあります。
ということで、ここの構文をもっと楽にしようというRFCが2019/01/23に提出されました。
Code free constructor
文法
class HOGE{
/**
* コンストラクタ
* @param int $foo
* @param string $bar
* @param array $baz
* @param DateTime $qux
*/
public function __construct(private int $foo, protected string $bar, public array $baz, DateTime $qux){
}
}
なんてこった全部消えた。
コンストラクタ引数は全て同名のプロパティに自動バインドされます。
可視性は引数に書かれているものが対応します。
$foo
はprivateの$this->foo
に、$bar
はprotectedの$this->bar
になる、ということです。
可視性が書かれていない$qux
は、単純にpublicになります。
extends
// 現在
class MyCustomMotorCycle extends MotorCycle {
public $passenger;
public function __construct(Person $driver, Person $passenger) {
parent::__construct("Custom", $driver);
$this->passenger = $passenger;
}
}
// 上と同じ
class MyCustomMotorCycle(Person $driver, Person $passenger)
extends MotorCycle("Custom", $driver) { };
引数の一部を親クラスにそのまま渡す場合は、そのプロパティは子クラスには設定されません。
無名クラス
// 現在
$a = new class($mDriver, $mPassenger) extends MotorCycle {
private $passenger;
public function __construct(Person $driver, Person $passenger) {
parent::__construct("Custom", $driver);
$this->passenger = $passenger;
}
};
// 同じ |------arguments------||-----------constructor params------------|
$a = new class($mDriver, $mPassenger)(Person $driver, private Person $passenger)
extends MotorCycle("Custom", $driver){};
無名クラスの文法は少々わかりづらいですね。
過去のRFC
2013年にAutomatic Property InitializationというRFCが提出されましたが、却下されています。
導入
PHP8で導入したい。
互換性のない変更
非互換はおそらくありません(Looks like no BI)。
感想
いや…あかんじゃろこれ。
何がよくないって、ショートハンドに傾倒するあまり人に優しくない。
特に、可視性を書いてないときは勝手にpublicになるのは悪手でしょう。
非互換はたぶんないとか書いてあるけど、このRFCが導入されたら、入れた覚えのないプロパティが勝手に増えるので、foreach
やproperty_exists
の動作が変わります。
extendsしたときの挙動も極めてわかりにくいですね。
あとコンストラクタで$this->foo = $bar
ってしたときに$this->bar
がどうなるのかよくわからない。
これならAutomatic Property Initializationの文法の方がまだいいと思います。
class Point
{
private $x;
public function __construct($this->x, $y);
}
こちらであれば、引数に$this->x
と書いたらプロパティに入る、普通に$y
と書いたら入らない、ということで、まだわかりやすいですね。
PHP internalにはこのようなRFCや、RFCに辿り着かないような思いつきが日々投稿されています。
しかし、思いつきの中にも時折光る原石があり、それらがやがてPHP本体に取り込まれることを考えると、全ての投稿やアイデアはきっと無駄ではありません。
Code free constructorはいったいどちらになるでしょうか。
まあ、これが投票まで行ったとしても採択されることはないと思いますが。