例外についてあまり使う機会がなかったので、簡単にまとめておきます。
例外とは
異常が発生したことを表すオブジェクト。
使用例としては、実行時に予想外のエラーが発生してプログラムが停止しないように、エラーを検知してプログラムの続きができるようになります。
例外を発生させる
Kernel.#raise
を使用すると、意図的にエラーを発生させることができます。
第一引数には例外クラスを指定する。第二引数には例外メッセージを指定します。
raise StandardError
raise StandardError, "error" #StandardError: error!
raise StandardError.new("error")
# それぞれの書き方があります
例外クラスの種類
上の例ではStandardError
を発生させましたが、Rubyで定義されている例外クラスを用いていろいろなErrorを発生させることができます。
raise StandardError, "error!" # => StandardError: error!
raise RuntimeError, "error!" # => RuntimeError: error!
raise SyntaxError, "error!" # => SyntaxError: error!
例外の種類については組込みライブラリ-例外を参照してください。
また、エラーメッセージだけを記載して定義することができますが、この時のエラーの補足はRuntimeError
になります。
初期値はRuntimeError
だということを覚えておきます。
raise "error!" # => RuntimeError
beginを使ってエラーを取得
begin~rescue
でエラーが発生する可能性のある処理を定義
rescue~end
でエラーが発生した時の処理を定義します。
begin
# 実行するコード定義
rescue
# エラー時の処理を定義
end
また、else
とensure
を定義して、エラーが発生しなかった時の定義と、エラーに関わらず実行される処理を定義することができます。
begin
# 実行するコード定義
rescue
# エラー時の処理を定義
else
# エラーが発生しなかった時の処理を定義
ensure
# エラーに関わらず実行される処理を定義
end
簡単な例を挙げます。
begin
p 3/3
rescue
p "error!"
else
p "no error!"
ensure
p "プログラムが処理されました"
end
# => 1
# => "no error!"
# => "プログラムが処理されました"
rescureでエラーの情報を取得
rescure => 変数名
でエラーの情報を取得することができます
begin
p 3/0
rescue => e
p e.class # 例外の種類を出力
p e.message # 例外のメッセージを出力
p e.backtrace # 例外が発生した位置情報を出力
end
# => ZeroDivisionError
# => "divided by 0"
# => ["sample.rb:2:in `/'", "sample.rb:2:in `<main>'"]
rescueでエラー毎に例外クラスを指定
rescue
の後に、例外のクラスを指定して、それぞれの例外のケースに合わせて処理を変えることもできます。
⇨@okuramasafumiさんのコメントより修正
begin
p 3/0
rescue ZeroDivisionError
puts "ゼロでは割れません"
rescue StandardError
puts "エラーが発生しました"
end
# => "ゼロでは割れません"が表示される
また、上から順番に定義した例外クラスとマッチしたものから止まるようになります。
begin
p 3/0
rescue StandardError
puts "エラーが発生しました"
rescue ZeroDivisionError
puts "ゼロでは割れません"
end
# => "エラーが発生しました"が表示される
raiseとbeginを組み合わせてみる
raiseでは例外を発生させることができるとお伝えしました。
begin~rescueに定義して実際に例外が発生して、取得できているか確認します。
begin
raise ZeroDivisionError.new("Error!")
rescue => e
p e.class #=> ZeroDivisionError
p e.message #=> "Error!"
p e.backtrace #=> "sample.rb:2:in `<main>'"
end
Retryで処理を再実行
rescue~end
でretry
を使用することで処理を再度実行することができる。
⇨@okuramasafumiさんのコメントより修正
count = 0
begin
p 3/0
rescue
p count += 1
if count < 2
retry
end
p "error"
end
# => 1
# => 2
# => "error"