LoginSignup
11
4

More than 5 years have passed since last update.

コンストラクタで毎回`$this->hoge = $hoge`と書くのがつらたん

Last updated at Posted at 2019-04-01

コンストラクタに引数を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が導入されたら、入れた覚えのないプロパティが勝手に増えるので、foreachproperty_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はいったいどちらになるでしょうか。

まあ、これが投票まで行ったとしても採択されることはないと思いますが。

11
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
4