eigenclass logo
MAIN  Index  Search  Changes  PageRank  Login

Rich exception hierarchies, multiple inheritance in Ruby

Rescue clauses are amongst the few things in Ruby that care about the class of your object, so when you do

begin
  ...
rescue Foo
  ...
end

the exception has got to be of kind Foo or a subclass. If rescueing exceptions followed the message sending paradigm, it could have looked like this fictitious snippet:

begin
  ...
rescue foo            # exception object responds to foo
  ...
rescue standard_error # corresponds to the current StandardError

In practice, the fact that rescue cares about the class means that you typically define your exceptions using

MyException = Class.new(StandardError)
# or class MyException < StandardError; end
# more "reload-safe" (but then again, getting a warning in that case can be
# good as you might not notice otherwise)

Indeed, Ruby wants the class used in the rescue clause to be derived from Exception. Since an unqualified rescue handles all StandardError and derived exceptions (but not all Exceptions), you'll often end up subclassing that exception class.

Ruby lacks multiple inheritance, so you cannot have an exception class that derives from e.g. both BackendError and CriticalError, making the following impossible, right?

def foo(*args)
  ...
rescue CriticalError
  # send message to your pager, subsystem shutdown
  # ...
  raise
rescue BackEndError
  # we can handle these locally when not critical...
end


# somewhere else
begin
  foo(*stuff)
rescue BackEndError
  # ...
end

Ruby does have multiple inheritance, it's just that it's been given another name (and it's got a couple restrictions).

You can also use modules to specify which exceptions are to be rescued (ruby-core:10618), allowing you to create rich exception hierarchies which might be useful in some scenario:

module CriticalError; end
module BackendError; end

class SomeError < Exception
  include CriticalError
  include BackendError
end

begin
  raise SomeError
rescue BackendError
  puts "Something's very wrong, shutting down"
  raise
end
# ~> -:10: SomeError (SomeError)
# >> Something's very wrong, shutting down



Last modified:2007/03/21 12:10:46
Keyword(s):[blog] [ruby] [frontpage] [exception] [multiple] [inheritance] [subpar]
References:[Message-oriented (duck-typed) exceptions]