はじめに
PHPマニュアルの型に関するページを見ていると、このような記述が書いてあります。
戻り値を void とした関数からリファレンスを返すことは、 推奨されなくなりました。
一見すると「戻り値をvoidとした関数は推奨されなくなりました。」のように見えて、「void型怖い…」「void型を使うのはやめよう…」となってしまうかもしれません。しかし、ここで記述されていることはリファレンスを返す関数の戻り値にvoid型を指定することが非推奨になったということであり、void型が非推奨になったというわけではありません。
リファレンスを返す関数
そもそも、リファレンスを返す関数とは何でしょうか。PHPマニュアルでは以下のような例が挙げられています。
<?php
class foo {
public $value = 42;
public function &getValue() {
return $this->value;
}
}
$obj = new foo;
$myValue = &$obj->getValue(); // $myValue は $obj->value へのリファレンス、つまり 42 となります
$obj->value = 2;
echo $myValue; // $obj->value の新しい値である 2 を表示します
?>
メソッドgetValue()
の左側に&
の記号がついています。これは、このメソッドがリファレンス(参照)を返すことを意味しています。getValue()
からはfoo
クラスのプロパティ$value
のリファレンスを受け取れるため、$obj->value
の値を変更すると$myValue
の値が変わることが確認できます。
返り値がvoid型のリファレンスを返す関数
対して、返り値がvoid型のリファレンスを返す関数とは何か。PHP 8.1 の RFC、Return by reference with void type の項目を確認すると以下のような例が挙げられています。
function &test(): void {}
- 関数名
test()
の左側に&
の記号がついているのでリファレンスを返す:値を返す - 戻り値の型がvoid:値を返さない
これは 「値を返す」と「値を返さない」のどちらの意味も含む、矛盾した書き方になっています。 PHP 8.1.0 からはこの矛盾した書き方を避けるために、返り値がリファレンスかつvoid型の関数を非推奨にしたようです。
void型を使用するメリット
void型はPHP 7.1.0 で追加されました。そのときのRFC、Void Return Type を確認すると以下のようなことが書かれています。
(戻り値の型を省略することで) 任意の値を返すことを指定する手段はすでにありますが、戻り値の型を持つ他の多くの言語とは異なり、値を返さないように指定する方法はありません。これは文書化やエラーチェックの目的で役立つ可能性があるため、これは残念です。特に、関数が結果を生成するのではなく、アクションを実行することが明確になります。
void型を使用すると、このようなメリットを享受することができそうです。
- 文書化やエラーチェックの目的で役立つ可能性がある
- 関数が値を返すのではなく、処理を実行するだけであることが明確になる
例えば、void型の関数が何らかの値をreturnしたとすると、実行時に Fatal error: A void function must not return a value
とエラーが出てくれます。
<?php
function test(int $number): void // void型なのに
{
return $number + 1; // 値を返している
}
var_dump(test(5));
まとめ
- PHP 8.1.0 で非推奨になったのは、返り値がリファレンスかつvoid型の関数
- 理由は矛盾した書き方だから
- 返り値がリファレンスではない関数でvoid型を使用することは問題ない
- void型を使用するのにはメリットがある
- 文書化やエラーチェックの目的で役立つ可能性がある
- 関数が値を返すのではなく、処理を実行するだけであることが明確になる