- 公開日
Rubyで独自例外を定義するときはStandardErrorを継承する
タイトルの通り、Rubyで独自例外を定義するときはException
ではなく、StandardError
を継承するしきたりとなっています。# `Exception`ではなく
class MyError1 < Exception; end
# `StandardError`.
class MyError2 < StandardError; end
理由をコードでみてみます。
Exception を継承した場合
class MyError1 < Exception; end
begin
raise MyError1
rescue => e
puts "Exception handled! #{e}"
end
# => MyError1: MyError1
MyError1 がrescue
節でハンドリングされてませんね。こうしてみるとどうでしょう。class MyError1 < Exception; end
begin
raise MyError1
rescue Exception => e
puts "Exception handled! #{e}"
end
# => Exception handled! MyError1
次はrescue
節に入りました。
StandardError を継承した場合
class MyError2 < StandardError; end
begin
raise MyError2
rescue => e
puts "Exception handled! #{e}"
end
# => Exception handled! MyError2
こちらは問題なくrescue
節でハンドルされました。
なぜ?
rescue は第1引数で指定した例外クラスの下の階層にある例外だけを補足するけど、引数を省略すると StandardErrorクラスを指定したものとみなすからだ。
via. Rubyで自前の例外クラスを作るときExceptionではなくStandardErrorを継承する理由
下記がビルトインのExceptionのサブクラスたちです。rescue
のデフォルトがStandardError
、raise
のデフォルトがRuntimeError
となっています。
- NoMemoryError
- ScriptError
- LoadError
- NotImplementedError
- SyntaxError
- SecurityError
- SignalException
- Interrupt
- StandardError – default for
rescue
- ArgumentError
- UncaughtThrowError
- EncodingError
- FiberError
- IOError
- EOFError
- IndexError
- KeyError
- StopIteration
- LocalJumpError
- NameError
- NoMethodError
- RangeError
- FloatDomainError
- RegexpError
- RuntimeError – default for
raise
- SystemCallError
- Errno::*
- ThreadError
- TypeError
- ZeroDivisionError
- SystemExit
- SystemStackError
- fatal – impossible to rescue
via Exception
よってrescue
のデフォルトで拾えるStandardError
を使って独自例外を定義しましょう。class MyError2 < StandardError; end