こんにちは。いっとくです!
都内でWebエンジニアやってまっす!
プログラミングってすごく奥深いな〜と思うことがあって、知識や経験が増えるほど、かつて「なにこれ?必要なん?」って思っていたことの重要さや便利さに気づいたりします。
そんなプログラミングの勉強を初めて間もない頃に全然理解できなかった便利機能のひとつがPHPの型宣言(タイプヒンティング)!
関数やメソッドを定義する際に引数を設定することがあると思うんですけど、型宣言をすることによって別のデータ型の引数が渡された際にエラーを出すことができるようになります。
そして、ぶっちゃけると僕はプログラミングを始めてしばらくするまで、この型宣言を使う意味が全くわからなかった。
だって、プログラミングを勉強した時に習わなかったし、頭がいい人が作った機能の意図を自分で読み解けるほど優秀でもなかったので。
しかし最近ようやくこの型宣言をすることの嬉しさがわかってきました!
ということで今回はプログラミングを勉強を始めたばかりで、型宣言をすることのメリットが一体なんなのか全然わからないという人のためになるべく噛み砕いて解説できればと思います!
僕はなぜ型宣言のメリットを理解できなかったのか
まず僕が初めて型宣言の書き方を知った時、このように思ったのです。
なんでわざわざ自分でエラーが出るポイントを増やさなきゃならんのだ??
そりゃそうです。プログラミングを始めた頃ってエラーが怖いんです。
というのも当時の僕にとってエラーっていうのはゲームでいうと「ミッション失敗」だったんですよ。
どこかで間違えたからエラーが出て、そのプログラムを完成させるというミッションに失敗したんだという感覚でした。
特にプログラミングってHTMLとかCSSから足を突っ込むことがほとんどだと思うんですけど、あれってエラー出ないじゃないですか。表示はぶっ壊れるけど。
だからエラーにも慣れていなくて、エラーが出る度に自分の無能さを突きつけられているような気がして怖かったんですよ。
型宣言は、その怖いエラーが出るパターンを増やすことなので、一体なにがしたいの?ドMなの?なんて思っちゃっていたわけです。
というわけで、タイプヒンティングの便利さを理解するためには、まずこのエラーがミッション失敗の通告ではなくて病気になりかかっているサインだと気づく必要があります。
僕らは怪我をすると痛みを感じますが、この痛みは体が危険に気づくために備わっているサインです。痛みがないと気づかないうちに血が出まくって死んでしまうかもしれません。
そして、エラーも同じくプログラムがぶっ壊れそうなサインなのです。
怪我と同じで精神的には痛いけど、これがないとプログラムが死んでしまうという重要なサインなので、適度に仲良くしていきましょう。
つまり、型宣言とはドMのプログラマーが自分の精神を追い詰めた縛りプレイを楽しむものではなく、いままで気づけなかった病気に気づくためのセンサーをつけるということなのです!
型宣言(タイプヒンティング)の嬉しいポイント
では型宣言をすることによる嬉しいポイントを簡単な例で見ていきましょう。
まずは型宣言をしていない関数を作っていく
<?php
$array = [
'犬',
'猫',
'牛',
'悪玉菌',
];
outputArray($array);
function outputArray($array) {
foreach ($array as $item) {
echo $item . '<br>';
}
}
上記のコードのように渡した配列の中身を全て出力するプログラムがあったとします。
しかし、もしこの関数に文字列を渡してしまった場合、foreachの引数で文字列を扱うことができないので、エラーが起きてしまいます。
<?php
$array = '犬';
outputArray($array);
function outputArray($array) {
foreach ($array as $item) {
echo $item . '<br>';
}
}
// Warning: Invalid argument supplied for foreach()というエラーが発生する
なので、関数内ではちゃんと配列が渡されたかどうかをチェックする必要があります。
<?php
$array = '犬';
outputArray($array);
function outputArray($array) {
if (!is_array($array)) {
$array = [
'お前',
'これ',
'配列じゃねぇから',
'やり直し!'
];
}
foreach ($array as $item) {
echo $item . '<br>';
}
}
これでなにが来ても安心ですね。
しかし、型宣言で引数の型を指定してあげれば、わざわざチェックしなくてもその前にエラーを出して気付くことができます。
<?php
$array = '犬';
outputArray($array);
// 引数の前に型を宣言することができる
function outputArray(array $array) {
foreach ($array as $item) {
echo $item . '<br>';
}
}
もちろんこんなシンプルな例だと普通はどう使えばいいか気付くし、どっちにしろエラー出るからいいんですが、PHPは割と規則がゆるい言語なので処理によってエラーは出てないくせに、間違ったまま動いてしまうということがあります。
それに後から気づいて、よくよく見直したらこの関数に別のデータ型を渡していたからだった!なんてなると、いちいち処理を遡ってチェックしないといけないので、気付くまでに時間がかかってしまいます。
実際に現場でプログラムを書いているとチーム開発になることが多いので、他の人が作った関数やメソッドを使うことがあります。
すると関数やメソッドが作成者の意図と異なった使われ方をする時があり、それが予期せぬバグを生み出したりします。
それが最初から型宣言をしておけば、間違ったままとりあえず動くみたいな状況に陥る前にここが間違ってますよー!と知ることができるようになるわけです。
使う側も指定されていれば、あぁここはなんか理由があってこの型を指定してるんだと気付くでしょう。
これが型宣言の大きなメリットでしょう!
チーム開発において自分が書いたコードの使い方をより具体的に他のプログラマーに伝えることで、バグが発生する確率を減らしていきます。
あと、もう一つのメリットは受け取った値チェックを型宣言に任せることもできます!
先ほど書いたコードではis_array()で配列かどうかをチェックしていましたが、型を指定することによってこの処理を丸ごと省略することができました。
同様に他の型が渡された場合もちゃんとした渡され方をしているかどうか、引数の型を指定するだけでチェックできちゃいます。
なお、PHPの型宣言で指定できる方と対応しているバージョンは以下の通り。
クラス名 or インターフェース名 | クラス名やインターフェース名を指定 | php5.0~ |
self | 渡された値が同じクラス内で定義されているかどうかを指定 | php5.0~ |
array | 配列のみを受けとる | php5.1~ |
callable | コールバック関数を受け取る | php5.4~ |
bool | boolean型の値(真偽値)のみ受け取る | php7.0~ |
float | float型(浮動小数点型)のみ受け取る | php7.0~ |
int | integer型(整数型)のみ受け取る | php7.0~ |
string | string型(文字列型)のみ受け取る | php7.0~ |
iterable | foreachで繰り返し処理が可能な値のみ受け取る(arrayやforeachで処理が可能なオブジェクトなど) | php7.1~ |
型宣言の書き方は下記のように関数やメソッドの引数の前に型を書くだけです
function myFunction1 (string $args) {
処理
}
function myFunction2 (int $args) {
処理
}
function myFunction3 (iterable $args) {
処理
}
function myFunction4 (クラス名 $args) {
処理
}
こうすることで、コード内でis_arrayやis_string、instanceofなどの型チェックを行わなくてもよくなるのでコードをスッキリさせることができます。
関数を呼び出す際に値をチェックをするということは当然計算量が増えるため、パフォーマンスに影響を与えるという話も聞いたことがあります。
ということで試しに計測してみましたが、体感できるような差が生まれるとは考えにくいくらいのものでした。
なのでできる限り型宣言を使った方が、安全でバグが見つかりやすいコードができるためメリットがあるように思えます。
以上、初見ではなかなかその便利さに気づかない型宣言の良さについてでした!
おしまい!
コメント