Ruby 公式リファレンスの StandardError には,
通常のプログラムで発生する可能性の高い例外クラスを束ねるためのクラスです。
とある。
つまり,NameError, ArgumentError, TypeError, ZeroDivisionError, RuntimeError といった「よく出くわすやつ」はみ〜んな StandardError のサブクラスというわけだ。
いや,本当にそうなのか?
実は,通常のプログラムでよく発生する例外なのに StandardError のサブクラスになっていないやつがある。
それ,な〜んだ?
例外クラスの継承関係は
https://docs.ruby-lang.org/ja/3.4/library/_builtin.html#:~:text=%E4%BE%8B%E5%A4%96%E3%82%AF%E3%83%A9%E3%82%B9
で確認しよう。
見つけた?
LoadError がそれだ。
require するライブラリー名をタイポしたらこれが出る。
ときどき見るよね?
LoadError は ScriptError のサブクラスになっていて,StandardError のサブクラスにはなっていない。
だから,
begin
require "hoge"
rescue StandardError
puts "そんなライブラリー知らん"
end
と書いてもダメ。rescue LoadError としなければならない1。
ScriptError のサブクラスには SyntaxError もある。
「こっちのほうが頻出では?」と思うかもしれないが,ちょっと位置付けが違う。
我々がふだんよく目にする SyntaxError は,書いたスクリプトに構文エラーがあって,実行が始まる前に起こるものだ。
だから
begin
x =. 1
rescue SyntaxError
puts "構文が間違っとる"
end
というスクリプトを実行しようとしても「構文が間違っとる」は表示されない。
スクリプトが構文的に間違っているので,実行すらされないのだ。
では,SyntaxError を捕捉するような機会はないのか?
ある。
こういう例だ
begin
eval "x =. 1"
rescue SyntaxError
puts "構文が間違っとる"
end
このスクリプト自体には構文上の問題はなく,実行される。
しかし,eval を実行するとき,与えられた文字列 "x =. 1" が Ruby のコードとして構文上の問題を抱えているので,SyntaxError が発生する。
-
LoadError の捕捉はしばしば必要になる。xxx というライブラリーが無いときに代わりに yyy を読み込む,とか。gem のソースコードで
LoadErrorを検索してみよう! ↩