はじめに
PHP 7.4の新機能としてクラスのプロパティに型がかけるようになる機能が提案されていました。これはTyped Properties 2.0と呼ばれるもの。日本語に治すとプロパティ型注釈といった感じでしょうか。仕様書は以下の通りです。
これが約1ヶ月前の2019年1月にマージされており、PHP 7.4で入ることが確定のようです。
以下、提案書を簡単に日本語で説明したものです。
機能の概要
スカラ型 *1 の型注釈の導入や、戻り値の型注釈の導入により、PHP7は型システムが非常に強化された。しかし現状クラスのプロパティには型をつけられないので、開発者はgetterやsetterをつかい、その引数や戻り値に型注釈をつけている。これはボイラーテンプレート *2 でありあまりよろしくない。
これを利用することで
class User { /** @var int $id */ private $id; /** @var string $name */ private $name; public function getId(): int { return $this->id; } public function setId(int $id): void { $this->id = $id; } ... }
こう書かれていたのがこうなる
class User { public int $id; public string $name; }
v1 との違い
実はプロパティ型注釈自体は提案されたことがある機能である*3。
しかしこのv1の機能は却下されている。v1とv2は何が違うのか。大きく2つある。
- staticプロパティもサポートしている。v1では実装上の問題で含まれていなかったらしい。
- 型注釈されたプロパティの参照渡しにも対応している(詳細は後述)。
対応している型
class Example { // voidとcallable以外は対応している public int $scalarType; protected ClassName $classType; private ?ClassName $nullableClassType; // staticプロパティでもOK public static iterable $staticProp; // varでもOK var bool $flag; // デフォルト値も設定可能 public string $str = "foo"; public ?string $nullableStr = null; // こう書いた場合は$xも$yもfloat public float $x, $y; }
callableについて
callableだけは扱いが文脈依存で非常に難しいので対応していません*4。これはcallableが「型のように使えるけど型ではない」性質によるもので、文脈に依存しないcallableが別で提案されています。Consistent Callablesというものです。
callableの代わりにClousureを使うという方法があります。
ちなみに対応している型は
- bool, int, float, string, array, object
- iterable
- self, parent
- クラス・インタフェース
- ?bool のようなnullable型
strict_types
引数や返り値の型注釈と同様に strict_types=1/0 が効きます。
継承
当然ながら親クラスと同じ名前で違う型のプロパティは定義できません。
class A { private bool $a; } class B extends A { public string $a; // ダメ }
トレイトも同様の制限を受けます。
将来の話: readonly
将来的には readonly
みたいなものが導入されると本当にgetter/setterを作る文化はなくなりそうだ。みたいな話が出ている。はやくreadonlyつくってくれ。
値の初期化
nullableでない型にデフォルト値を設定しない場合
class Test { public int $n } $test = new Test(); echo $test->n; // ここで初めて型エラーになる
これは、クラスとかだとデフォルト値を設定できないから。
class Test { // ここではAnotherClassのデフォルト値を設定できない public AnotherClass $a; public function __construct() { // 呼ばれる前にsetされていればセーフ $this->a = new AnotherClass; } } $test = new Test(); $test->a; // aをsetしていなかったらここでエラーになる
nullableでない型のプロパティをunset仕様としてもエラーになる。
class Test { public int $val = 1; } $test = new Test(42); var_dump($test->val);
参照渡し
$aryの型が変わらなければこういうことも可能です。
class Test { public array $ary = [3, 2, 1]; } $test = new Test; sort($test->ary);
さいごに
他にも細かい仕様がいろいろ書かれていますが、これ以上は知らなくても問題なく書けそう。 強いて言えばunsetした場合の挙動が気になったくらい。PHP7.4がリリースされたらぜひ使ってみてください。
参考
- 作者: 小川雄大,柄沢聡太郎,橋口誠
- 出版社/メーカー: 技術評論社
- 発売日: 2010/11/12
- メディア: 大型本
- 購入: 32人 クリック: 1,065回
- この商品を含むブログ (59件) を見る
- 作者: たにぐちまこと
- 出版社/メーカー: マイナビ出版
- 発売日: 2018/04/26
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る