Rubyの例外について
Rubyのbegin-rescueについて勘違いしていたのでメモ。
Rubyでは、Object->Exception->StandardErrorのような継承構造になっており、独自の例外クラスを作って識別する際には、Exceptionを継承するのではなく、StandardErrorを継承した方が(俺の)思っているとおりの動作になる。
Exceptionを継承した場合、rescue句でクラス名を省略したブロックではハンドルされない。
StandardErrorを継承した場合、rescue句でクラスを省略したブロックでもハンドルされる。
もっとも、他の例外に埋もれないように独自例外を使うような気もするので、Exceptionから継承してもいいのかな?とも思う。この辺は哲学を学ばないとダメかもしれない。
ひとまず、テストコードを書いて確かめたのでメモしておく。この辺詳しい人教えてください。
#!/usr/bin/ruby -Ku # -*- coding: utf-8 -*- require 'pp' class TestError < StandardError; end class TestException < Exception; end class Test def raise_error raise TestError, "exception message of TestError" end def raise_exception raise TestException, "exception message of TestException" end end t = Test.new puts "・StandardExceptionを継承した場合は、rescueでクラス名を指定しなくてもハンドルできる" begin puts " クラス名を指定しない場合" t.raise_error rescue puts "caught raise_error's exception: #{$!.message}" end puts puts "・Exceptionを継承した場合は、rescueでクラス名を指定しないとハンドルできない" begin puts " クラス名を指定する場合" t.raise_exception rescue TestException puts "caught raise_exception's exception: #{$!.message}" end puts begin puts " クラス名を指定しない場合(rescueでハンドルできず、最後のputsまでたどり着かない)" t.raise_exception rescue puts "caught raise_exception's exception: #{$!.message}" end puts "exit..."
実行結果:
・StandardExceptionを継承した場合は、rescueでクラス名を指定しなくてもハンドルできる クラス名を指定しない場合 caught raise_error's exception: exception message of TestError ・Exceptionを継承した場合は、rescueでクラス名を指定しないとハンドルできない クラス名を指定する場合 caught raise_exception's exception: exception message of TestException クラス名を指定しない場合(rescueでハンドルできず、最後のputsまでたどり着かない) ./exception.rb:14:in `raise_exception': exception message of TestException (TestException) from ./exception.rb:41