В чем разница между вызовом исключений и созданием исключений в Ruby?

StackOverflow https://stackoverflow.com/questions/51021

  •  09-06-2019
  •  | 
  •  

Вопрос

Ruby имеет два разных механизма исключений:Бросок/Поймать и Поднимать/Спасать.

Почему у нас двое?

Когда следует использовать одно, а не другое?

Это было полезно?

Решение

Я думаю http://hasno.info/ruby-gotchas-and-caveats имеет достойное объяснение разницы:

поймать/бросить – это не то же самое, что поднять/спасти.catch/throw позволяет вам быстро выйти из блоков обратно в точку, где catch определен для определенного символа, а поднять спасение - это настоящая обработка исключений, включающая объект Exception.

Другие советы

  • raise, fail, rescue, и ensure ручка ошибки, также известен как исключения
  • throw и catch являются поток управления

В отличие от других языков, бросок и улов Руби не используются для исключений.Вместо этого они предоставляют способ прекратить исполнение на ранней стадии, когда дальнейшая работа не требуется.(Гримм, 2011)

Завершение одного уровня потока управления, например while цикл, можно сделать с помощью простого return.Завершение многих уровней потока управления, например вложенного цикла, можно выполнить с помощью throw.

Хотя механизм исключений подъема и восстановления отлично подходит для прекращения выполнения, когда что-то идет не так, иногда полезно иметь возможность выпрыгнуть из какой-то глубоко вложенной конструкции во время обычной обработки.Вот тут-то и пригодятся ловля и бросок.(Томас и Хант, 2001 г.)

Рекомендации

  1. Гримм, Авди."Брось, поймай, поднимай, спаси ... я так запутался!" Блог Rubylearning.Н.п., 11 июля 2011 г.Веб.1 янв.2012. http://rubylearning.com/blog/2011/07/12/throw-catch-raise-rescue--im-so-confused/.
  2. Томас, Дэйв и Эндрю Хант.«Программирование рубины». :Руководство прагматичного программиста.Н.П., 2001.Веб.29 сент.2015. http://ruby-doc.com/docs/ProgrammingRuby/html/tut_Exceptions.html.

https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise предлагает превосходное объяснение, которое я сомневаюсь, что смогу улучшить.Подводя итог, я по ходу дела беру несколько примеров кода из поста в блоге:

  1. raise/rescue являются ближайшими аналогами throw/catch конструкцию, с которой вы знакомы по другим языкам (или Python raise/except).Если вы столкнулись с ошибкой и хотите throw над этим на другом языке, вам следует raise в Руби.

  2. Руби throw/catch позволяет прервать выполнение и подняться вверх по стеку в поисках catch (нравиться raise/rescue делает), но на самом деле не предназначен для ошибок.Его следует использовать редко, и только тогда, когда «идите вверх по стеку, пока не найдете соответствующее». catch«Поведение имеет смысл для алгоритма, который вы пишете, но не имеет смысла думать о throw как соответствующее состоянию ошибки.

    Для чего в Ruby используются ловля и бросок? предлагает несколько советов по хорошему использованию throw/catch построить.

Конкретные поведенческие различия между ними включают:

  • rescue Foo спасет экземпляры Foo включая подклассы Foo. catch(foo) только поймаю тот же объект, Foo.Мало того, что ты не можешь пройти catch имя класса, чтобы перехватывать его экземпляры, но оно даже не выполняет сравнения на равенство.Например

    catch("foo") do
      throw "foo"
    end
    

    даст вам UncaughtThrowError: uncaught throw "foo" (или ArgumentError в версиях Ruby до 2.2)

  • Можно перечислить несколько статей о спасении...

    begin
      do_something_error_prone
    rescue AParticularKindOfError
      # Insert heroism here.
    rescue
      write_to_error_log
      raise
    end
    

    в то время как несколько catchэто должно быть вложенным...

    catch :foo do
      catch :bar do
        do_something_that_can_throw_foo_or_bar
      end
    end
    
  • Голый rescue эквивалентно rescue StandardError и является идиоматической конструкцией.«Голый catch", нравиться catch() {throw :foo}, никогда ничего не поймает и не должен использоваться.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top