如果您尝试在 Ruby 中调用
nil
对象的方法,则会出现 NoMethodError
异常,并显示以下消息:
"undefined method ‘...’ for nil:NilClass"
try
方法,如果发送到 nil
对象,则仅返回 nil
:
require 'rubygems'
require 'active_support/all'
nil.try(:nonexisting_method) # no NoMethodError exception anymore
那么
try
如何在内部工作以防止这种异常?
ActiveSupport 4.0.0 定义了两个
try
方法: one 用于 Object
实例:
class Object
def try(*a, &b)
if a.empty? && block_given?
yield self
else
public_send(*a, &b) if respond_to?(a.first)
end
end
end
other 用于
NilClass
实例(nil
对象):
class NilClass
def try(*args)
nil
end
end
现在,假设我们有一个
Object
实例(不包括 nil
,它实际上继承自 Object
,就像 Ruby 中的其他所有内容一样),定义一个返回 nil
的方法:
class Test
def returns_nil
nil
end
end
因此,运行
Test.new.try(:returns_nil)
或 Test.new.not_existing_method
,会调用 Object#try
,它会检查公共方法是否存在(respond_to?
);如果确实如此,则调用该方法(public_send)
,否则返回 nil
(没有其他行)。
如果我们在这些返回
try
方法中调用另一个 nil
:
Test.new.try(:returns_nil).try(:any_other_method)
Test.new.try(:not_existing_method).try(:any_other_method)
我们称之为
NilClass#try
,即nil#try
,它简单地忽略一切并返回nil
。因此,在 try
实例上调用任何其他 nil
并返回 nil
。
与 Ruby 中的所有其他对象一样,
nil
有一个类 (NilClass
),该类具有方法。例如,在 nil?
上定义 NilClass
返回 true,这就是为什么 nil.nil?
不返回 NoMethodError
。
Ruby 中的每个类都可以开放(用新方法更新)。 Rails 打开
NilClass
添加 try
方法并让它返回 nil
(这也是为什么即使链中的一个步骤返回 try
也可以链接 nil
,因为后续的 nil
也 回复 try
)。
来自 Rails (3.2) 文档:
# Object#try:
def try(*a, &b)
if a.empty? && block_given?
yield self
else
__send__(*a, &b)
end
end
# NilClass#try (http://apidock.com/rails/NilClass/try):
def try(*args)
nil
end
方法
try
只是为 nil
对象单独实现,因此它始终返回 nil
,即使您尝试调用的方法是为 nil
对象实现的。
它忽略参数并仅返回
nil
。这是实现:
class NilClass
def try(*args)
nil
end
end
请注意,此实现始终返回
nil
,即使 nil
响应该方法:
nil.try(:to_i) # => nil, rather than 0