如果您尝试在Ruby中的nil
对象上调用方法,则会出现NoMethodError
异常,并显示以下消息:
"undefined method ‘...’ for nil:NilClass"
但是,Rails中有一个try
方法,如果它被发送到nil
对象,则只返回nil
:
require 'rubygems'
require 'active_support/all'
nil.try(:nonexisting_method) # no NoMethodError exception anymore
那么try
如何在内部工作以防止该异常呢?
答案 0 :(得分:3)
与Ruby中的每个其他对象一样,nil
有一个类(NilClass
),它有方法。例如,nil?
上定义了NilClass
以返回true,这就是nil.nil?
不返回NoMethodError
的原因。
ruby中的每个类都可以打开(使用新方法更新)。 Rails会打开NilClass
以添加try
方法并让它返回nil
(即使链中的一个步骤返回try
,也可以链接nil
的原因},因为后续nil
也响应try
)。
答案 1 :(得分:2)
来自Rails(3.2)documentation:
# 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
对象实现的。
答案 2 :(得分:2)
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
。
答案 3 :(得分:1)
它忽略了参数,只返回nil
。这是implementation:
class NilClass
def try(*args)
nil
end
end
请注意,即使nil
响应方法,此实现也始终返回nil
:
nil.try(:to_i) # => nil, rather than 0