Ruby 的 throw
语句接受任何 Object
,这意味着下面的任何一个都是合法的。
throw BasicObject
throw 123456.78
throw "wow"
throw :doge
但是,根据我的理解,我选择抛出 Symbol
有两个原因。
- 必须
捕获
与抛出的完全相同的对象
。这意味着执行catch "wow"
将导致UncaughtThrowError
。使用Symbol
时这不是问题。 catch
后无法引用抛出的对象
。要指定返回值,可以将其输入为第二个参数:throw :doge, "wow"
在我看来,这会破坏抛出自定义Object
的全部意义..
此外,令人困惑的是,在 ruby 1.9
之前,throw
的(第一个)参数过去仅限于 Symbols
。这是否意味着有人必须抛出
非符号,并且 ruby 必须更改其实现以允许此类用例?或者是其他什么......比如节省类型检查的执行时间。
此时,我唯一能想象到的与 Symbol
不同的是 Fixnum
,但这就是更改的原因吗?请赐教。
最佳答案
假设您正在使用一些您不关心其内部结构的库。如果该库使用带有某个符号(或任何其他常见对象)的 throw
方法,而该符号(或任何其他常见对象)意外地与您要抛出
的符号(或对象)相同,该怎么办? - 在你自己的代码中?这会导致不必要的交互。另一方面,如果创建自定义对象并抛出它,则不必关心此类问题。特别是如果您仅将其定义为局部变量,那么它是安全的。如果将其定义为常量,那么它会相对安全(危险在于其他库不小心在同一 namespace 中使用了相同的常量名称)。
catch
创建一个 Object
实例,并将其分配为 block 变量,这使其安全。
当我使用throw
时,我通常不能使用 block 变量形式,因为大多数时候,我throw
和catch
在不同的地方方法。因此,我创建了一个 Object
实例,并将其指定为私有(private)常量,这使得它相对安全。
class SomeClass
Foo = Object.new
private_constant :Foo
def some_method
...
catch(Foo){... another_method ...}
...
end
def another_method
...
throw(Foo)
...
end
end
关于ruby - 为什么有人会扔出一个非符号呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35450221/