phpの型宣言(タイプヒンティング)|nullとかオブジェクトとか色々調べたみた
今日ボーっとtwitterを眺めていると、面白いツイートを見つけた。
function print_count(int $count) {
echo "チョコを{$count}個もらいました";
}
という関数を
print_count('1個もチョコ、もらえませんでした');
で呼び出すと「チョコを1個もらいました」と出力してくれるPHPは優しかった。— suin❄️PHPでオブジェクト指向 (@suin) February 14, 2019
最近phpをやり始めたばかりなので、phpで型宣言ができるとは知らなかった。(php5までは「型宣言」のことは「タイプヒンティング」と呼んでいた。参考:PHP: 関数の引数 - Manual)
そこで今日は、phpの型宣言について色々調べてみたよ。
phpの型宣言(タイプヒンティング)とは?
phpの型宣言とは、名前の通り関数の引数の型を指定できる機能のこと。
例えば、以下のコードの様に関数の引数をint $num
と書いてあげることで、引数にはinteger
型のみ受け付けるようにできる。
<?php
function mult_two(int $num) {
return $num * 2;
}
echo mult_two(2);
?>
そもそも、型宣言をすると何が嬉しいかと言うと、以下の2点が挙げられる。
- 本来期待している型と異なる型が引数に格納されることで起こる、思わぬバグを防げる
- コードが読みやすくなる。
例えば、$num
にはinteger
型が入ってほしいけど間違えてstring
型を入れてしまった場合等は、型宣言をしておくことでエラーを表示してくれるので、間違いに気付きやすくなる。
また、他人のコードを読む作業は疲れるものだが、関数の引数と戻り値の型が分かるだけでも読みやすさが違ってくるので、型を明示するのは良い。(コメントとしても書くけど)
phpにはどんな型宣言(タイプヒンティング)ができるか?
phpでは、以下の9つの型宣言を行える。(php7.3時点)
php 5.0.0から
- クラス、インターフェース名
- self、オブジェクト自身
version5.0.0はクラス関係のものが型宣言できていた。
php 5.1.0から
- array、配列
php 5.4.0から
- callable、ざっくり言うと関数
php7.0.0から
- bool true/falseのやつ
- float
- int
- string
- iterable、繰り返し関連(配列とかオブジェクトとか連想配列)
iterableとは、厳密には「array, traversable, instanceof」と公式では定義されている。上記の一覧を見てわかるように、基本的にはphp7.0.0以降を使っておけば、型変換については問題ないだろう。
参考記事:PHP: Traversable - Manual
戻り値の型宣言(タイプヒンティング)はできるのか?
結論から言うと、php7から戻り値の型宣言ができるようになった。戻り値で使える型は、引数と全く同じだ。
参考記事:PHP: 返り値 - Manual
戻り値の型宣言の方法は、引数の後にコロンを入力して、その後に型を宣言すると良い。例えば、以下の様に行う。
<?php
function mult_two(int $num): float {
return $num * 2;
}
var_dump(mult_two(2)); // float(4) と表示
?>
上記のコードでは、戻り値の型宣言をしなければint
型の4が表示されるが、float
型を宣言することで、戻り値が型変換されてfloat
型の4として返されいるのが分かる。
上記のコードではint
型からfloat
型に型変換されるからエラーがでなかったが、型宣言をfloat
からarray
に変えると、以下の様に「mult_two()
の戻り値はint
でなければダメだよ」と言うエラーが発生する。
PHP Fatal error: Uncaught TypeError: Return value of mult_two() must be of the type array, integer returned in /home/hogehoge/sam.php:7
型宣言としてのnullとかvoidとか
php7.1からは型宣言としてnull
やvoid
が使えるようになった。
例えば、null
型の場合は型宣言の先頭に?
を付ければ良い。
function test(?string $name)
{
var_dump($name);
}
でも、正直nullの型宣言をいつ使うのは今の所分かっていない。
おそらく、void
の方が実用性は高いだろう。
function swap(): void
{
処理
}
void
を使えばC言語チックに戻り値がない事を明記できるので、個人的には使う頻度は高い。
おまけ:suinさんのツイート内のコードが上手く動かない件
本記事の冒頭にsuinさんのツイートを紹介した。
function print_count(int $count) {
echo "チョコを{$count}個もらいました";
}
という関数を
print_count('1個もチョコ、もらえませんでした');
で呼び出すと「チョコを1個もらいました」と出力してくれるPHPは優しかった。— suin❄️PHPでオブジェクト指向 (@suin) February 14, 2019
個人的にはすごく面白いと思ったのだが、どうやらphp7.1以降は上記のツイート内のコードはエラーが発生してしまうようだ。
Warning: A non-numeric value encountered in
参考記事:PHP: その他の変更 - Manual
なので、上記のコードを動かしたい場合は、phpのバージョンを7.0未満に下げる必要がある。