Search code examples
exceptionsmalltalkpharosqueak

Raising a customized error/exception


I'm playing around with Pharo, and would like to raise a customized error/exception/something, but I've got no idea how.
I've browsed the relevant (I think) chapters of "Pharo by Example" and "Deep into Pharo"; but couldn't make heads or tails about it - it seems way above the level that I need...

I've got a setter for a variable, and would like to raise an error/exception if the input isn't an Integer:


    MyClass >> someVariable: anInteger
       anInteger isInteger
          ifFalse: [ self SomehowProtestLoadly - the part I don't know how to do ].
       someVariable := anInteger

Just aborting or exiting would be sufficient... but if possible, I'd like to do it with a bit more "flare" - and in a more explainatory way...


Solution

  • The easiest way is to just signal a generic error:

    someVariable: anInteger
      anInteger isInteger
        ifFalse: [self error: 'must be an Integer'].
      someVariable := anInteger
    

    Now, if you want to signal a specific error, do the following:

    1. Create a subclass of Error, say, NonIntegerArgument
    2. Write your code like this

      someVariable: anInteger
        anInteger isInteger
          ifFalse: [NonIntegerArgument signal: 'must be an Integer'].
        someVariable := anInteger
      
    3. For handling this exception do the following

      [myObject someVariable: self value]
        on: NonIntegerArgument
        do: [:ex | self handleException: ex]
      

    Note that your exception could provide more information, say the actual argument that was sent. To do this add an instance variable to your NonIntegerArgument class, namely, argument. Add a getter and a setter for it. Then

    NonIntegerArgument class >> #signal: aString argument: anObject
      ^self new
        argument: anObject;
        signal: aString
    

    and use it this way

    someVariable: anInteger
      anInteger isInteger
        ifFalse: [
          NonIntegerArgument
            signal: 'must be an Integer'
            argument: anInteger].
      someVariable := anInteger
    

    Now, the ex variable will be able to respond with the argument of the offending message.