Skip to main content
Engineering LibreTexts

12.7: Signaling an Exception

  • Page ID
    45957
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    To signal an exception1, you only need to create an instance of the exception class and send it the message signal, or signal: with a textual description. The class Exception class provides a convenience method signal, which creates and signals an exception. Here are two equivalent ways to signal a ZeroDivide exception:

        ZeroDivide new signal.
        ZeroDivide signal.    "class-side convenience method does the same as above"
    

    You may wonder why it is necessary to create an instance of an exception in order to signal it, rather than having the exception class itself take on this responsibility. Creating an instance is important because it encapsulates information about the context in which the exception was signaled. We can therefore have many exception instances, each describing the context of a different exception.

    When an exception is signaled, the exception handling mechanism searches in the execution stack for an exception handler associated with the class of the signaled exception. When a handler is encountered (i.e., the message on:do: is on the stack), the implementation checks that the exceptionClass is a superclass of the signaled exception, and then executes the handlerAction with the exception as its sole argument. We will see shortly some of the ways in which the handler can use the exception object.

    When signaling an exception, it is possible to provide information specific to the situation just encountered, as illustrated in the code below. For example, if the file to be opened does not exist, the name of the non-existent file can be recorded in the exception object:

    StandardFileStream class»oldFileNamed: fileName
        "Open an existing file with the given name for reading and writing. If the name has no
            directory part, then default directory will be assumed. If the file does not exist, an
            exception will be signaled. If the file exists, its prior contents may be modified or
            replaced, but the file will not be truncated on close."
        | fullName |
        fullName := self fullName: fileName.
        ^(self isAFileNamed: fullName)
            ifTrue: [self new open: fullName forWrite: true]
            ifFalse: ["File does not exist..."
                (FileDoesNotExistException new fileName: fullName) signal]
    

    The exception handler may make use of this information to recover from the abnormal situation. The argument ex in an exception handler [:ex | ...] will be an instance of FileDoesNotExistException or of one of its subclasses. Here the exception is queried for the filename of the missing file by sending it the message fileName.

    | result |
    result := [(StandardFileStream oldFileNamed: 'error42.log') contentsOfEntireFile]
        on: FileDoesNotExistException
        do: [:ex | ex fileName , ' not available'].
    Transcript show: result; cr
    

    Every exception has a default description that is used by the development tools to report exceptional situations in a clear and comprehensible manner. To make the description available, all exception objects respond to the message description. Moreover, the default description can be changed by sending the message messageText: aDescription, or by signaling the exception using signal: aDescription.

    Another example of signaling occurs in the doesNotUnderstand: mechanism, a pillar of the reflective capabilities of Smalltalk. Whenever an object is sent a message that it does not understand, the VM will (eventually) send it the message doesNotUnderstand: with an argument representing the offending message. The default implementation of doesNotUnderstand:, defined in class Object, simply signals a MessageNotUnderstood exception, causing a debugger to be opened at that point in the execution.

    The doesNotUnderstand: method illustrates the way in which exception-specific information, such as the receiver and the message that is not understood, can be stored in the exception, and thus made available to the debugger.

    Object»doesNotUnderstand: aMessage
        "Handle the fact that there was an attempt to send the given message to the receiver
            but the receiver does not understand this message (typically sent from the machine
            when a message is sent to the receiver and no method is defined for that selector)."
        MessageNotUnderstood new
            message: aMessage;
            receiver: self;
            signal.
        ^ aMessage sentTo: self.
    

    That completes our description of how exceptions are used. The remainder of this chapter discusses how exceptions are implemented and adds some details that are relevant only if you define your own exceptions.


    1. Synonyms are to “raise” or to “throw” an exception. Since the vital message is called signal, we use that terminology exclusively in this chapter.

    This page titled 12.7: Signaling an Exception is shared under a CC BY-SA 3.0 license and was authored, remixed, and/or curated by Alexandre Bergel, Damien Cassou, Stéphane Ducasse, Jannik Laval (Square Bracket Associates) via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.