Ruby的throw
语句接受任何Object
,这意味着以下任何一项都是合法的。
throw BasicObject
throw 123456.78
throw "wow"
throw :doge
但是,根据我的理解,我选择抛出Symbol
有两个原因。
catch
投掷完全相同的Object
。这意味着执行catch "wow"
会产生UncaughtThrowError
。使用Symbol
时,这不是问题。Object
后无法引用被引发的catch
。要指定一个返回值,可以将其作为第二个参数输入:throw :doge, "wow"
这会破坏我认为抛出自定义Object
的全部意义.. 此外,令人困惑的是throw
的(第一个)参数在Symbols
之前曾被限制为ruby 1.9
。这是否意味着有人必须throw
非符号,并且ruby必须更改其实现以允许此类用例?或者它是别的......比如节省类型检查的执行时间。
此时,我唯一可以想象的是Symbol
s与Fixnum
s分开,但这是改变的原因吗?请赐教。
答案 0 :(得分:5)
假设您正在使用一些您不关心其内部的库。如果该库使用throw
方法与某个符号(或任何其他常见对象)意外碰巧与您throw
相同的符号(或对象) - 在您自己的代码中?它会导致不必要的交互。另一方面,如果您创建自定义对象并将其抛出,则无需关心此类问题。特别是如果您仅将其定义为局部变量,那么它将是安全的。如果将其定义为常量,那么它将是相对安全的(危险是其他库在同一名称空间中意外使用相同的常量名称)。
catch
创建Object
的实例,并将其指定为块变量,这样可以确保安全。
当我使用throw
时,我通常无法使用块变量形式,因为大多数时候,我throw
和catch
使用不同的方法。因此,我创建了Object
的实例,并将其指定为私有常量,这使其相对安全。
class SomeClass
Foo = Object.new
private_constant :Foo
def some_method
...
catch(Foo){... another_method ...}
...
end
def another_method
...
throw(Foo)
...
end
end