質問: 開発者が予めエラーを想定し、想定したエラーが発生したときに行う処理を例外処理と呼び、 その想定したエラーを例外と呼びます。そして、その例外にphpに予め組み込まれているexceptionクラスとその子クラスのインスタンスを送ることを例外が投げられた、と言います。 例外"が"ということは、エラーが投げられたということでしょうか。 インスタンスを送信しているので、exceptionが投げられたのほうがシックリくるのですが、なぜ例外"が"投げられたというのでしょうか。
回答: 以下、PHP に限らない、手続き型のプログラミング言語一般の話です。 「例外」=「想定内のエラー」というのはちょっと違うかもしれません。 例外処理の要諦は、異常状態の処理と大域脱出にあると考えています。 ある関数やメソッドの中では、何らかのひとまとまりの処理を行うわけですが、その「通常処理(業務ロジックって言ったりもする)」ができないような「異常状態」も存在するわけです。頑健性のあるシステムを構築するには、異常状態への対処もしなければならないわけですが、関数内に異常状態に対する処理と本来の通常処理が混在した形になっていると、通常処理の流れがわかりにくくなり、実装上・仕様上のバグに気づきにくくなるし、業務ロジックの変更についていくの困難になってしまいます。そこで、異常状態を検出したら通常処理の流れから飛び出すように書ける、というのが例外機構を備えたプログラミング言語の利点なわけです。 余談ですが、手続き型のプログラミング言語において、「通常処理の流れから飛び出す」もう一つの仕組みが return 文です。例外機構を持たないプログラミング言語では、異常状態を検出したらその異常状態を表すものを return しちゃう、という書き方をすることで、異常状態の処理と通常処理とをわけることができます。 大域脱出というのは、通常のフローでは (return 文によって) 関数の呼び出し元にしか戻れないところ、呼び出し元の呼び出し元の呼び出し元の ... 呼び出し元まで一気に戻れる、ということです。言い方を変えると、飛んできた例外を捕まえる (捕捉する、catch する) 記述をしてあるところまで一気に戻ることができるわけですが、一気に戻るための記述が例外を投げる (throw) という表現になるわけです。 最初に戻ります。エラーとは何か、異常とは何か、という定義問題にもなってくるわけですが、「通常処理ができない条件」というのをとりあえずここでは「異常」と言ったわけですが、それは必ずしも「エラー」ではないことも多いわけです。「通常処理」のフローをきれいに書くために、「通常処理ができない条件」への対処を分離して書くのが例外処理です。 大域脱出できる、という点に着目し、(全然エラーじゃないし、「異常」でもないようなケースで)フロー制御の一部として利用する方法もあります。 たとえば、`forEachPerson()` という、管理している `person` について繰り返しコールバック関数を適用するような関数があって、次のように使えるとします。 ``` forEachPerson(function($person) { echo $person['id'] . ':' . $person['name']; }); ``` このとき、`id` がある値以上になったら繰り返しを中断したい、というときに例外を使って ``` try { forEachPerson(function($person) { if ($person['id'] > 100) { throw new Exception('id が 100 超えたんで途中で抜けるよ'); } echo $person['id'] . ':' . $person['name']; }); } catch (Exception $e) { // do nothing } ``` 例外処理は一般的に重いので、速度が要求されるところで気軽に使うのは考えものかもしれませんが。