21

好的,我确实有以下代码

 def update_state_actions
    states.each do |state|
      @state_turns[state.id] -= 1 if @state_turns[state.id] > 0 && state.auto_removal_timing == 1
    end
  end

现在排在...

 @state_turns[state.id] -= 1 if @state_turns[state.id] > 0 && state.auto_removal_timing == 1

它说错误

in 'block update_state_actions' : Undefined method '>' for nil:NilClass <NoMethodError>

错误的原因是什么?怎么来>被认为是一种方法,但它是一个逻辑运算符?

4

2 回答 2

56

为什么 > 被认为是一种方法,但它是一个逻辑运算符?

没有问题。在 Ruby 中,当您编写类似 的表达式时1 + 2,在内部它被理解为:在接收器上1.+( 2 )调用方法,并作为单个参数。另一种理解方式是,您正在将消息发送到 object 。#+12[ :+, 2 ]1

错误的原因是什么?

现在在你的情况下,由于某种原因@state_turns[ state.id ]返回nil。所以表达式@state_turns[state.id] > 0变成nil > 0了 ,正如我之前所说的,它被理解为调用#>方法 on nil。但是您可以检查NilClass所属nil的 没有#>在其上定义实例方法:

NilClass.instance_methods.include? :> # => false
nil.respond_to? :> # => false

因此,该NoMethodError异常是一个合法错误。通过引发这个错误,Ruby 保护了你:它很早就告诉你你@state_turns[ state.id ]的不是你想象的那样。这样,您可以更早地纠正错误,并成为更高效的程序员。此外,Ruby 异常可以通过begin ... rescue ... end语句来挽救。Ruby 异常通常是非常友好和有用的对象,您应该学习如何在软件项目中定义自定义异常。

为了进一步扩展这个讨论,让我们看看你的错误来自哪里。当你写一个类似的表达式nil > 10时,实际上是nil.>( 10 )Ruby 开始#>nil. 您可以通过键入以下内容查看查找链:

    nil.singleton_class.ancestors #=> [NilClass, Object, Kernel, BasicObject]

该方法将在祖先链的每个模块中进行搜索:首先,Ruby 会检查是否#>定义了 on NilClass,然后 on Object,然后Kernel,最后,BasicObject。如果#>在其中任何一个中都找不到,Ruby 将继续尝试method_missing方法,再次按查找链的所有模块的顺序。如果甚至method_missing不处理该:>消息,NoMethodError则会引发异常。为了演示,让我们通过插入一条自定义消息来定义#method_missing方法,该消息将出现而不是:ObjectNoMethodError

class Object
  def method_missing( name, *args )
    puts "There is no method '##{name}' defined on #{self.class}, you dummy!"
  end
end

[ 1, 2, 3 ][ 3 ] > 2 
#=> There is no method '#>' defined on NilClass, you dummy!

为什么它不像 NullPointerException 那样说

Ruby 中没有这样的例外。检查Ruby的Exception类。

于 2013-11-03T09:55:59.553 回答
2

必须将其转换为整数变量才能执行操作:

  • @state_turns [state.id] .to_i > 0
  • state_a = state.auto_removal_timing.to_i + 1
于 2016-10-25T02:17:22.483 回答