Rescue clauses are amongst the few things in Ruby that care about the class
of your object, so when you do
begin...rescueFoo...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...rescuefoo# exception object responds to foo...rescuestandard_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)...rescueCriticalError# send message to your pager, subsystem shutdown# ...raiserescueBackEndError# we can handle these locally when not critical...end# somewhere elsebeginfoo(*stuff)rescueBackEndError# ...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: