5

如果您尝试nil在 Ruby 中调用对象上的方法,则会NoMethodError出现异常消息:

"undefined method ‘...’ for nil:NilClass"

但是,tryRails 中有一个方法,nil如果它被发送到一个nil对象,它就会返回:

require 'rubygems'
require 'active_support/all'

nil.try(:nonexisting_method) # no NoMethodError exception anymore

那么如何在try内部工作以防止出现这种异常呢?

4

4 回答 4

3

像 Ruby 中的所有其他对象一样,nil有一个类 ( NilClass),它有方法。例如,nil?被定义NilClass为返回 true,这就是为什么nil.nil?不返回 a NoMethodError

ruby 中的每个类都可以打开(用新方法更新)。Rails 打开NilClass以添加try方法并让它返回nil(这也是为什么try即使在链中的一步返回时也可以链接nil,因为后续nil 也会响应try)。

于 2013-10-07T12:32:49.713 回答
2

来自 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只是为nilobject 单独实现,因此它总是返回nil,即使您尝试调用的方法是为nilobject 实现的。

于 2013-10-07T12:24:11.427 回答
2

ActiveSupport 4.0.0 定义了两种try方法:一种是用于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

另一个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)or Test.new.not_existing_methodObject#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

于 2013-10-07T12:47:43.400 回答
1

它忽略参数并只返回nil. 这是实现

class NilClass
  def try(*args)
    nil
  end
end

请注意,此实现始终返回nil,即使nil响应方法:

nil.try(:to_i) # => nil, rather than 0
于 2013-10-07T12:29:56.857 回答