You construct exception handlers by sending the message when:do: to a block. You can install multiple handlers simultaneously by using repeated forms of when:do: (that is, when:do:when:do:, when:do:when:do:when:do:, and so on) for up to five handlers. Because the handlers are tried in order, more general handlers should be placed later in the list. You can use nesting to allow more than five handlers if absolutely required.
The first argument to when:do: is an instance of class ExceptionalEvent. The second argument is a one-argument handler block that is passed the instance of Signal that describes the exception.
When an exception is signaled, the most recent when:do: matching the exception is evaluated first. When a when:do: message is found with either the exception or a more general exception (one of the exception's ancestors) as the when argument, its handlerBlock is run.
Within the handler block, the following methods can be sent to an instance of Signal:
Assuming that ThatException is a global variable, an application could have the following code:
"Initialization code." (ThatException := ExAll newChild) description: 'That exception occurred.'. thatMethod "Answer true if thatTest completes without error, otherwise signal ThatException." self thatTest failed ifTrue: [ ThatException signal ]. ^true
Note: | The application has determined that an exceptional condition has occurred and signals an exception. |
anyMethod "The application can then do something like the following. Answer true if thatMethod completes without exception, and false otherwise." ^[ self thatMethod ] when: ThatException do: [:signal | "Handle the exception in some way: increment a counter, print a message, fix a problem, ... and then exit the handler." signal exitWith: false].
Note: | From do: [:signal to the end is the handler block. |
Note that "dropping off the end" of a handler block is equivalent to sending
resumeWith: (Association key: #resume value: valueOfTheBlock
where valueOfTheBlock is the value of the handler block.
Note: | Neither the handler block nor the block that receives
when:do: can contain a return (^)
expression. Although this is not a significant limitation, it should be
kept in mind when automatic code generation techniques are used, because
arbitrary code fragments cannot be wrapped with exception handlers without
first checking for return expressions.
|