PHP8.4 readonlyプロパティの動きが少し変わっていた
この記事は カオナビ Advent Calendar 2024 シリーズ2 20日目の記事です。
はじめに
PHP8.4のリリース後にPHPマニュアルを見ているとreadonlyプロパティの説明に少し追記があった。
PHP 8.4.0 より前のバージョンでは、readonly プロパティは暗黙的に private-set であり、 同じクラス内からのみ書き込みが可能でした。
PHP 8.4.0 以降では、readonly プロパティは暗黙的に protected(set) となり、 子クラスからも設定可能です。必要に応じて明示的に オーバーライドすることもできます。
なるほど、どういうことか少し検証してみた。
検証
サンプルコードはこちらです。
<?php
class HelloWorld
{
readonly public string $say;
public function __construct()
{
$this->say = 'Hello World';
}
}
class HelloNewWorld extends HelloWorld
{
public function __construct()
{
$this->say = 'Hello New World';
}
}
上記のサンプルコードをためしにこちらで実行してみる。
PHP8.2、8.3では実行できないが、PHP8.4では実行できるようになっていますね。(マニュアル通りですね。)
(こんなコードは書かないって人は多いかもしれないが、)
PHP8.3以前では次のように子クラス側でプロパティをオーバーライドすることで値の書き換えを行なっていたが、PHP8.4以降では不要になりそうです。
class HelloNewWorld extends HelloWorld
{
readonly public string $say;
public function __construct()
{
$this->say = 'Hello New World';
}
}
再度ためしに実行してみると,,,
PHP8.2、8.3、8.4で動いていますね。
ただし、コンストラクタのプロモーションを使っている場合はあまり意識する必要はないかもしれないです。
class HelloNewWorld extends HelloWorld
{
public function __construct(readonly public string $say = 'Hello New World')
{
}
}
こちらでもPHP8.2、8.3、8.4で動いていますね。
まとめ
PHP8.4ではプロパティフック、非対称可視性プロパティといった新機能が注目されますが、
既存の機能に対しても色々と変更が入っていることも多いので、マニュアルはしっかり見ましょうね。
今回の発見ではあまり感じないけど、
別の何かの変更からコードが思わぬ動きをして、デバッグ地獄に陥るかもしれませんよ!っていうお話です。
Discussion