Ruby 中的错误处理 ( 下 )

yufei       6 年, 3 月 前       871

Ruby 中的错误处理 ( 上 ) 章节中我们学习了 Ruby 的错误处理的一些基础知识,其实,这已经能够应付 50% 的情况了,相比于其它的语言教程,我们似乎还漏了一个最重要的东西没讲解,那就是自定义错误 ( custom error )。

但,就这些了吗?

不是,Ruby 还提供了另一个非常有意思的关键字 retry 用来重入触发了错误的代码块。

本章节,我们对这两个知识点做一些简单的介绍。

retry 关键字

retry 关键字用于重新执行 begin ... end 块中包含的代码。例如下面的代码,当 i 的值小于 3 的时候就会重新执行一次

i = 0

begin
  i += 1
  puts "retry ##{i}"

  raise RuntimeError
rescue RuntimeError => e
  retry if i < 3

输出结果如下

retry #1
retry #2
retry #3

注意,重新执行并不是重置执行,因为 i 变量在外部定义,当第一次执行时会输出 retry #1 然后抛出了异常

当使用 retry 关键字重新执行时,此时的 i 已经通过 i += 1 增长到了 2 。以此类推,直到 i > 3 再也不满足重新执行的条件了,所以最终的输出结果如上,而不是

retry #1
retry #1
retry #1

当然了,如果把 i=0 放入 begin 语句,会报错的。

需要注意的另一点是,begin ... rescue ... end 子句可以访问调用范围的变量。

但,retry 关键字只能在 rescue 内部调用,否则会抛出一个 SyntaxtError 错误,例如下面的代码

irb> retry
SyntaxError: Invalid retry

自定义错误

Ruby 内置的错误已经能满足大部分的要求,但总有那么几次,需要能够自己定义错误,尤其是在开发框架的时候。

前一章节中我们提到,所有的 Ruby 错误,都必须有一个 Exception 祖先。这句话反过来也适用,就是,包含了 Exception 类作为祖先的类,都可以作为一个错误被 raise 抛出。

也就是说,我们可以通过简单地声明一个继承自其祖先链中包含 Exception 类的类的新类来创建新的错误类型

class PolicyError < Exception
end

class UserPolicyError < PolicyError
end

begin
  raise PolicyError, 'access not granted'
rescue PolicyError => policy_error
  puts "#{policy_error.class}: #{policy_error.message}"
end

begin
  raise UserPolicyError, 'user unauthorized'
rescue UserPolicyError => user_policy_error
  puts "#{user_policy_error.class}: #{user_policy_error.message}"
end

运行结果如下

PolicyError: access not granted
UserPolicyError: user unauthorized

上面的代码中,UserPolicyError 直接继承自 PolicyError 类,而 PolicyError 类直接从 Exception 继承。

你有没有尝试过,当使用 raise 抛出一个祖先中不包含 Exception 类的类会怎么样 ?

直接上代码试一下就知道结果了呗,哈哈

class NotAnError
end

raise NotAnError

输出结果如下

TypeError (exception class/object expected)

也就是说,如果 Kernel#raise 方法抛出的错误类的祖先中不包含 Exception ,则会抛出另一个错误 TypeError

结束语

我本以为自己会讲解的很透彻,结果讲解的超级肤浅。哎

目前尚无回复
简单教程 = 简单教程,简单编程
简单教程 是一个关于技术和学习的地方
现在注册
已注册用户请 登入
关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.