Squak Smalltalk [6 * 9 = 42] whileTrue: [World run]
Stopařův průvodce jedním převážně neškodným programovacím jazykem
smalltalk
Swiki
  • Domů
  • Zpět
  • Tento server

    Squeak
  • Úvod
  • Smalltalk
  • Články
  • Knihy
  • Dokumentace
  • FAQ
  • Tutoriály
  • Download
  • Odkazy

    Komunita
  • CSSUG
  • Oznámení
  • Projekty
  • O nás
  • Fórum
  • Kontakt

     

  • Výjimky

    K moderním programovacím jazykům neodmyslitelně patří zpracování výjimek. U Smalltalku tomu není jinak, ovšem pár rozdílů lze najít. Např. oproti Javě zde virtuální stroj hraje mnohem méně významnou úlohu.

    Ve Smalltalku hrají výjimky velmi významnou roli, což je mimo jiné dáno tím, že kontrola kódu v době kompilace je z principu velmi omezená.

    Nejjednodušší zpracování výjimek

    Nejčastěji používanou konstrukcí je použití metody ifError: třídy BlockContext.
    [ localVar := 42 / 0 ] ifError: [ Transcript show: 'chyba' ]
    

    Protože se jedná o výraz, lze ho výhodně použít pro bezpečné přiřazení
    localVar := [ 42 / 0 ] ifError: [ Float infinity ]
    

    v našem případě se vygeneruje výjimka ZeroDivide, tedy dělení nulou

    Blok pro zpracování výjimky může mít dle potřeby až dva parametry:
    • textový popis výjimky
    • příjemce výjimky
    [ 42 / 0 ] 
      ifError: [:error :receiver | Transcript show: error. receiver inspect ]
    
    "vypíše do Transcriptu řetězec 'ZeroDivide' a otevře inspector 
    pro objekt 42 třídy Integer"

    Zpracování výjimek

    [ 42 / 0 ] on: ZeroDivide do: [:exception | Transcript show: 'Dělení nulou' ].

    metoda on:do: třídy BlockContext má dva parametry
    • handler výjimky či množinu handlerů
    • blok vykonávaný v případě výskytu výjimky
    [ 42 / 0 ] on: ZeroDivide, Warning do: [:exception | Transcript show: 'Chyba' ].
    "nebo:"
    [ 42 / 0 ] on: (ExceptionSet with: ZeroDivide with: Warning) 
               do: [:exception | Transcript show: 'Chyba' ].

    Užitečná může být varianta onDNU:do:, která zachytává výjimky třídy MessageNotUnderstood

    Generování výjimek

    Základní třídou pro výjimky je třída Exception. Z ní je možné odvodit další typy výjimek.

    Nejčasněji používané odvozené třídy výjimek jsou např. Error, Warning, Notification, Halt apod.

    Výjímky se generují metodou signal
    Error signal.
    Error signal: 'Text chyby'.
    Warning signal: 'Text varování'.
    Notification signal: 'Text upozornění'.

    Reakce na výjimku

    Výjimky mohou umožňovat návrat (isResumeable). V tom případě nám poslouží metody resume nebo resume:, popřípadě retry či retryUsing.

    Výjimku propustíme voláním metody pass

    Blok zpracování výjimky můžeme opustit zavoláním metody return či return:

    Finalizační kód

    Pokud například pracujeme se souborem, chceme, aby byl na konci práce vždy uzavřen. V případě, že však nastane neošetřená výjimka, k uzavření souboru dojít nemusí. Pro tento a podobné účely je vhodné použít následující obrat:

    [ "zpracovávej soubor" ] ensure: [ "uzavři soubor" ].

    K uzavření souboru pak dojde za všech okolností. Pokud v prvním bloku dojde k výjimce, je zpracována standardním způsobem.

    Příklad 1

    Zpracování bez výskytu chyby
    | block val |
    block := [ Transcript clear; show: 'before'; cr.
      val := 42/1.
      Transcript show: 'after'; cr.
      'block result'
    ] on: Error do: [:ex | Transcript show: 'ex before'; cr.
                             "akce"
                             Transcript show: 'ex after'; cr.
                             'exception block result'
    ].
    Transcript show: 'val: '; show: val; cr.
    Transcript show: 'block: '; show: block; cr.
    "
    before
    after
    val: 42
    block: block result
    "

    Příklad 2

    Vyskytla se chyba
    | block val |
    block := [ Transcript clear; show: 'before'; cr.
      val := 42/0.
      Transcript show: 'after'; cr.
      'block result'
    ] on: Error do: [:ex | Transcript show: 'ex before'; cr.
                             "akce"
                             Transcript show: 'ex after'; cr.
                             'exception block result'
    ].
    Transcript show: 'val: '; show: val; cr.
    Transcript show: 'block: '; show: block; cr.
    "
    before
    ex before
    ex after
    val: nil
    block: exception block result
    "

    Příklad 3

    Návrat
    | block val |
    block := [ Transcript clear; show: 'before'; cr.
      val := 42/0.
      Transcript show: 'after'; cr.
      'block result'
    ] on: Error do: [:ex | Transcript show: 'ex before'; cr.
                             ex resume.
                             Transcript show: 'ex after'; cr.
                             'exception block result'
    ].
    Transcript show: 'val: '; show: val; cr.
    Transcript show: 'block: '; show: block; cr.
    "
    before
    ex before
    after
    val: nil
    block: block result
    "

    Příklad 4

    Návrat s vnucením hodnoty
    | block val |
    block := [ Transcript clear; show: 'before'; cr.
      val := 42/0.
      Transcript show: 'after'; cr.
      'block result'
    ] on: Error do: [:ex | Transcript show: 'ex before'; cr.
                             ex resume: 6*9.
                             Transcript show: 'ex after'; cr.
                             'exception block result'
    ].
    Transcript show: 'val: '; show: val; cr.
    Transcript show: 'block: '; show: block; cr.
    "
    before
    ex before
    after
    val: 54
    block: block result
    "

    Příklad 5

    Nový pokus
    | block val |
    block := [ Transcript clear; show: 'before'; cr.
      val := 42/0.
      Transcript show: 'after'; cr.
      'block result'
    ] on: Error do: [:ex | Transcript show: 'ex before'; cr.
                             ex retry.
                             Transcript show: 'ex after'; cr.
                             'exception block result'
    ].
    Transcript show: 'val: '; show: val; cr.
    Transcript show: 'block: '; show: block; cr
    "
    before
    ex before
    ... neustále cyklí ...
    "

    Příklad 6

    Provedení náhradního bloku
    | block val |
    block := [ Transcript clear; show: 'before'; cr.  
      val := 42/0.
      Transcript show: 'after'; cr.
      'block result'
    ] on: Error do: [:ex | Transcript show: 'ex before'; cr.
                             ex retryUsing: [val := 42/1. 'retryBlock'].
                             Transcript show: 'ex after'; cr.
                             'exception block result'
    ].
    Transcript show: 'val: '; show: val; cr.
    Transcript show: 'block: '; show: block; cr.
    "
    before
    ex before
    val: 42
    block: retryBlock
    "

    Příklad 7

    Propuštění výjimky
    | block val |
    block := [ Transcript clear; show: 'before'; cr.  
      val := 42/0.
      Transcript show: 'after'; cr.
      'block result'
    ] on: Error do: [:ex | Transcript show: 'ex before'; cr.
                             ex pass.
                             Transcript show: 'ex after'; cr.
                             'exception block result'
    ].
    Transcript show: 'val: '; show: val; cr.
    Transcript show: 'block: '; show: block; cr.
    "
    before
    ex before
    ... vyskočí dialog ZeroDivide ...
    "

    Příklad 8

    Předčasný návrat z výjimkového bloku (obdoba ^)
    | block val |
    block := [ Transcript clear; show: 'before'; cr.  
      val := 42/0.
      Transcript show: 'after'; cr.
      'block result'
    ] on: Error do: [:ex | Transcript show: 'ex before'; cr.
                             ex return.
                             Transcript show: 'ex after'; cr.
                             'exception block result'
    ].
    Transcript show: 'val: '; show: val; cr.
    Transcript show: 'block: '; show: block; cr.
    "
    before
    ex before
    val: nil
    block: nil
    "

    Příklad 9

    Předčasný návrat z výjimkového bloku s návratovou hodnotou
    | block val |
    block := [ Transcript clear; show: 'before'; cr.  
      val := 42/0.
      Transcript show: 'after'; cr.
      'block result'
    ] on: Error do: [:ex | Transcript show: 'ex before'; cr.
                             ex return: 'předčasná hodnota'.
                             Transcript show: 'ex after'; cr.
                             'exception block result'
    ].
    Transcript show: 'val: '; show: val; cr.
    Transcript show: 'block: '; show: block; cr.
    "
    before
    ex before
    val: nil
    block: předčasná hodnota
    "

    Příklad 10

    Transformace výjimky
    | block val |
    block := [ Transcript clear; show: 'before'; cr.  
      val := 42/0.
      Transcript show: 'after'; cr.
      'block result'
    ] on: Error do: [:ex | Transcript show: 'ex before'; cr.
                             ex resignalAs: Notification new.
                             Transcript show: 'ex after'; cr.
                             'exception block result'
    ].
    Transcript show: 'val: '; show: val; cr.
    Transcript show: 'block: '; show: block; cr.
    "
    before
    ex before
    after
    val: nil
    block: block result
    "

    Příklad 11

    Chyba ve výjimkovém bloku
    | block val |
    block := [ Transcript clear; show: 'before'; cr.  
      val := 42/0.
      Transcript show: 'after'; cr.
      'block result'
    ] on: Error do: [:ex | Transcript show: 'ex before'; cr.
                             42/0.
                             Transcript show: 'ex after'; cr.
                             'exception block result'
    ].
    Transcript show: 'val: '; show: val; cr.
    Transcript show: 'block: '; show: block; cr.
    "
    before
    ex before
    ... vyskočí dialog ZeroDivide ...
    "





    Odkaz na tuto stránku

    • Články, poslední úprava dne 17 Únor 2010 v 11:18:52 uživatelem localhost





    Administrátoři: Pavel Křivánek, Zbyněk Křivka