Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

Rubyの例外処理の裏側──rescueがどの例外を捕捉するかを決めるエレガントな仕組み

Rubyで例外処理を扱ったことがある方なら、rescueにクラスを指定して、どの例外を捕捉するか選べることをご存じでしょう。

begin
  raise ArgumentError
rescue ArgumentError
  # `ArgumentError` を捕捉する
end

さらに、親クラスを指定すると、その子クラスにあたる例外もまとめて捕捉されることもご存じのはずです。

begin 
  raise ArgumentError
rescue StandardError
  # `ArgumentError` は `StandardError` を継承しているため、
  # ここで捕捉される
end

ここでいう「親」「子」とは、単純にクラス継承の関係を指しています。Rubyのソースコードの奥深くには、次のような定義が存在します。

class ArgumentError < StandardError
   ...
end

興味深いトリック

ここで一つ疑問です。Rubyは、発生した例外が指定されたクラスを継承しているかどうかを、一体どうやって判断しているのでしょうか?

最も素直な発想としては、is_a?kind_of?メソッドを使う方法が思い浮かびます。イメージとしてはこんな感じです。

if the_exception.is_a?(StandardError)
   # rescue処理を行う
end

しかし実際のRubyはそうしていません。代わりに、より興味深い===演算子を採用しています。

if StandardError === the_exception
   # rescue処理を行う
end

a === bという書き方に馴染みがない方のために説明すると、これは通常「bは、aが定義するグループに本質的に属するか?」という問いに答えるためのものです。具体例を見てみましょう。

(1..10) === 5             # true
('a'..'f') === "z"        # false

String === "hello"        # true
String === 1              # false

/[0-9]{3}/ === "hello123" # true
/[0-9]{3}/ === "hello"    # false

そして重要なのは、=====と同じくごく普通のRubyメソッドであるという点です。つまり、自分で定義し直すことができます。

class RedThings
   def self.===(thing)
     thing.color == :red
   end
end

ここまでの情報を整理してみましょう。rescue===を使って捕捉対象の例外を判定していること。そして、===は自由にオーバーライドできること。この2つを組み合わせれば、「どの例外を捕捉するか」をその場で動的に決定するクラスを作れるということになります。

class SevereMatcher
  def self.===(exception)
    exception.message =~ /severe/    
  end
end

begin
  raise RuntimeError, "Something severe happened"
rescue SevereMatcher
  # メッセージに "severe" という単語を含む例外を、
  # クラスに関係なくすべて捕捉する
end

このトリックを一度知ってしまえば、あとは想像力次第です。

まとめ

正直に言えば、動的な例外マッチャーを作成する場面に遭遇することは、それほど多くないかもしれません。しかし、kind_of?ではなく===を使うといった一見些細な実装上の選択が、Rubyを大きく柔軟で面白い言語にしている好例として、この挙動は非常に興味深いと言えます。内部実装への理解が深まると、普段使っている機能の新たな可能性にも気づけるものです。

  1. FedoraとUbuntuを徹底比較:どちらがあなたに合っている?

    「どのLinuxディストリビューションを使えばいいのか?」——これはLinuxユーザーの間で昔から繰り返されてきた永遠のテーマです。この話題はしばしば熱い議論を呼び、各ディストリビューションのファンが自陣営への勧誘をしてくることも珍しくありません。そんな中で特に名前が挙がるのがFedoraとUbuntuの2つ。本記事ではこの2大ディストリビューションを徹底的に比較し、どちらがあなたに適しているのかを探っていきます。 FedoraとUbuntuの基本情報 まずは基本から押さえておきましょう。本記事では、それぞれの最新リリースである「Fedora 32 Workstation」と「Ubunt

  2. Allo vs WhatsApp徹底比較:どちらのメッセージアプリがあなたに合っている?

    Googleの新メッセージアプリ「Allo」は、WhatsAppの王座を奪うことができるのでしょうか?リリース当初から話題を集めてきたこのアプリですが、世界的人気を誇るWhatsAppにとって本当に脅威となる存在なのか気になるところです。世界中の見出しを飾ったプライバシー問題はさておき、総合的なユーザー体験という観点では、果たしてどちらのアプリが優れているのでしょうか?どちらを使うべきか迷っている方のために、それぞれのアプリが持つメリットをわかりやすくご紹介します。自分に合った選択をする際の参考にしてみてください!WhatsAppを選ぶべき理由WhatsAppは多くの人にとっておなじみの存在で