Rubyの例外とその捕捉――基本のbegin〜rescue〜endからensure、else、retry、後置rescueまで:若手エンジニア/初心者のためのRuby 2.1入門(9)(1/4 ページ)
オープンソースのオブジェクト指向プログラミング言語「Ruby」の文法を一から学ぶための入門連載。最新版の2.1に対応しています。今回は、例外とその補足について、begin、rescue、end、ensure、else、retry、後置rescueなどの基本的な使い方を交えて解説します。
用法用量を守ってお行儀良く使いたい「例外」とは
連載8回目に当たる前回の「Rubyの面白さを理解するためのメソッド、ブロック、Proc、lambda、クロージャの基本」では、メソッドやブロックといった仕組みについて、さらに掘り下げて解説しました。前回学んだ知識は、メタプログラミングを学ぶための基礎となります。
連載9回目の今回は、他のオブジェクト指向言語でもポピュラーな仕組みである例外について学びます。例外の仕組みをうまく使うことによって、あるべきファイルが存在しない場合や、RubyプログラムからHTTPを使ってデータを取得できない場合などに、適切に対処できるようなプログラムを書くことができます。
多くのオブジェクト指向言語では、「例外」とその「捕捉」という仕組みを使うことで、エラーが発生した場合の処理を記述できます。ここでいうエラーとは、存在しないファイルを開こうとするなど、実行時の状況に依存するようなエラーです。また、例外の仕組みを利用することで、「メソッドが期待しないような引数が渡されたときに例外を投げてプログラマーに知らせる」というようなこともできます。
例外を使うと、オブジェクトとしてエラーに関する情報を扱えるので、エラー処理を簡潔に分かりやすく記述できます。一方で、C言語におけるgoto文のように「処理の流れをねじ曲げてしまう」という側面もあるので、用法用量を守ってお行儀良く使う必要があります。
Rubyの「例外」には、どんなものがあるのか、発生させてみる
ゼロ除算エラー――ZeroDivisionError
数学においては、「ある数を0で割ることはできない(定義されていない)」とします。Rubyでも同様に、整数は0で割ることはできず、いわゆる「ゼロ除算エラー」となります。pryで確かめてみましょう。
[1] pry(main)> 42 / 0 ZeroDivisionError: divided by 0 from (pry):1:in `/'
期待通りエラーが出ました。2行目の「ZeroDivisionError」は、どのような種類のエラーであるかを表す例外クラスです。Rubyでは全てがオブジェクトで成り立っているので、例外の種類に応じて多くのクラスが定義されています。続く「divided by 0」というのは、発生したエラーを端的に説明するメッセージです。
3行目では、どのメソッドの実行時に例外が発生したのかを教えてくれています。この場合は、「/」メソッド(連載第2回で紹介しましたが、Rubyでは演算子もメソッドであることを思い出してください)で例外が発生したことを知らせてくれています。
好きなタイミングで例外を発生させる――RuntimeError
クラスを設計するときに、プログラマーが任意に例外を発生させたいこともあるでしょう。典型的な例としては、作成したメソッドの引数が非負の整数であることを期待するのに、負の整数が渡されてきた場合などです。
このような場合には、Kernelモジュールで定義されている「Kernel.raise」メソッドを利用します。通常、Kernelモジュールのメソッドは「Kernel.」を省略できるので、以下のように例外を発生できます。
[1] pry(main)> raise "something wrong" RuntimeError: something wrong from (pry):1:in `__pry__'
2行目で、raiseメソッドの引数に与えた文字列がそのままメッセージとして利用されているのが分かります。また、エラーの種類を示す例外クラスはRuntimeErrorです。RuntimeErrorは、数ある例外クラスのどれにも属さないようなエラーを表す、いわば汎用的な例外クラスです。
Ruby組み込みの例外クラス一覧
ここまで、ZeroDivisionErrorとRuntimeErrorを紹介しましたので、この勢いで主要なRuby組み込みの例外クラスを一覧として以下にまとめます。詳細は、「Rubyリファレンスマニュアル - 組み込みクラス」を確認してください。
・Exception ├・NoMemoryError ├・ScriptError │└(スクリプトの実行に関するいくつかのエラーが含まれます) ├・SecurityError ├・SignalException │└Interrupt ├・StandardError │├・ArgumentError │├・EncodingError ││└(文字エンコーディングに関するいくつかのエラーが含まれます) │├・FiberError │├・IOError ││└・EOFError │├・IndexError ││└(添字に関するいくつかのエラーが含まれます) │├・LocalJumpError │├・Math::DomainError │├・NameError ││└・NoMethodError │├・RangeError ││└・FloatDomainError │├・RegexpError │├・RuntimeError │├・SystemCallError ││└(システムコールなどで発生する多くのエラーが含まれます) │├・ThreadError │├・TypeError │└・ZeroDivisionError ├・SystemExit ├・SystemStackError └・fatal
全ての例外はExceptionクラスを継承しています。中でも注目すべきは、StandardErrorクラスです。StandardErrorクラスを継承する各例外クラスは、アプリケーションレベルの例外です。StandardErrorクラスを継承しない例外クラス(例えばNoMemoryErrorなど)は、システムレベルの例外です。
このように、アプリケーションレベルでの例外とシステムレベルでの例外を区別できるような継承関係にしておくことで、例外を捕捉するときに役立ちます。もし、「メモリが足りない」などのシステムレベルの例外を捕捉してしまっても、アプリケーションレベルでできることは非常に限られるからです。
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- 公用語に英語、「再起動」したRubyKaigi 2013が東京で開催
いったん終了していたRubyコミュニティ主催の年次イベントが再開。技術色、国際色を強め、盛況のうちに幕を閉じた - Web業界、今から行くならRubyエンジニアが狙い目?
不況で冷え込んでいたIT業界の転職市場に、回復の兆しが見え始めている。だが、業種や職種によって採用数や条件に大きな差異が生まれている。転職市場の動向を追い、自身のキャリア戦略立案に生かしてほしい。 - Ruby 2.0.0がリリース、大規模化対応の機能などを搭載
生誕20年となる節目を迎えて、プログラミング言語「Ruby」の最新版がリリースされた - 新バージョンで何が変わるのか、Rubyはどこへ向かうのか:まつもと×笹田、Ruby 1.9を語る
- いよいよ始まるRuby 1.9への移行:開発コアメンバが語るRubyの今とこれから(前編)
- Rubyの今後の進化の方向性とは?:開発コアメンバが語るRubyの今とこれから(後編)
- 互換性や脆弱性の問題にどう対応していくのか:Rubyが抱える課題、NaClの前田氏が講演
- Rails Hub情報局:「なんでRubyなんか作った!? 迷惑だ!」に対するMatzの答え
- Rails Hub情報局:Rubyはイノベーション言語として選ばれている
- Rails Hub情報局:Rubyのまつもと氏は、一発屋で終わるのか?
- Rails Hub情報局:Rubyに魔法は要らない
- 数々の“スペル”で高度なプログラミング:Rubyの魔術
- 晴読雨読@エンジニアライフ:『たのしい開発 スタートアップRuby』――なぜRubyistたちはあれほど楽しそうなのか
- 「JRuby 1.7.0」登場、1年半ぶりのメジャーアップデート
JavaVM上のRuby実装「JRuby」の最新版となる「JRuby 1.7.0」が、10月22日にリリースされた。