8-1-3 例外処理の構文と例外クラスをおさえよう

例外を捕捉するための基本的な構文

発生した例外を捕捉するには、beginendで処理を囲みます。

例外が発生しそうな箇所をbeginrescueで囲み、rescueensureで例外が発生した場合の処理を囲みます。

ensureendには、例外が発生してもしなくても実行される処理を記述します。

ensure句は省略可能で、省略された場合は例外が発生した場合の処理はrescue〜endで囲まれた部分になります。

いずれも実行する処理は、インデントして記述するのが一般的です。

rescue句は、rescue 例外クラス => 変数と記述することで、例外のパターン毎に実行する処理を分けることができます。

処理を分けたい例外パターンが複数ある場合はrescue句を複数記述します。

また、=>という記号の後に変数を指定することで、発生した例外の内容(例外クラスのオブジェクト)をrescue句の中で変数を使うことができます。

なお、rescue句の例外クラスと変数はいずれも省略可能です。

例外が発生した場合処理を繰り返すretry

begin句の実行処理で例外が発生した場合、rescue句の中でretryと記述すると、処理をbegin句の処理を再度繰り返すことができます。

ただしretryをそのままで記述すると例外が発生し続ける限り無限ループになってプログラムの実行が終了しないことになりかねませんので注意が必要です。

前ページ「8-1-2 例外処理と例外クラスを理解するプログラムを記述してみよう」の例では、begin句の処理は未定義の変数aを参照しようとしているのでずっと例外を出し続けます。

そこで、begin句の処理を実行する回数を最大3回までに制限しています。実行結果から、その様子が分かります。

例外クラス

Rubyでは、あらゆるものがクラスやオブジェクトで定義されています。例外もまた、クラスとして定義されています。

前ページ「8-1-2 例外処理と例外クラスを理解するプログラムを記述してみよう」のrescue => eの例では、変数eには例外クラスのオブジェクトが代入されます。

rescue句でpメソッドで変数eを出力した結果を確認すると、NameErrorまたはNoMethodErrorクラスのオブジェクトであることが分かるでしょう。

なお、e.messageと、例外オブジェクトのmessageメソッドでエラーメッセージだけを取り出すこともできます。

例外クラスには様々なものがあります。

前ページ「8-1-2 例外処理と例外クラスを理解するプログラムを記述してみよう」の例では、NoMethodErrorクラスの親クラスを継承関係を遡って確認するプログラムを記述しました。

実行結果から、NoMethodErrorNameErrorStandardErrorExceptionObjectという継承関係であることが分かります。

Rubyには、その他にもたくさんの例外クラスが存在します。予期せぬ例外が発生した場合、これらの例外クラスが何をあらわすのかを知ることで、問題解決に役立つでしょう。

例外処理の構文と例外クラスのまとめ

  • 予期せぬ問題を捕捉する為の仕組みとして例外処理がある
  • 例外を捕捉したい処理をbegin句、例外が発生した場合に実行したい処理をrescue句に記述する
  • 例外もクラスで定義されており、例外が発生した場合は例外オブジェクトを参照して問題解決する