nil的未定义方法’>’:NilClass

好的,我有以下代码

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  

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

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

这没有问题。 在Ruby中,当你编写一个像1 + 2这样的表达式时,在内部它被理解为1.+( 2 ) :在接收器1上调用方法#+ ,其中2作为单个参数。 理解相同的另一种方法是,您将消息[ :+, 2 ]发送到对象1

错误的原因是什么?

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

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

因此, NoMethodErrorexception是合法错误。 通过引发此错误,Ruby会保护您:它会提前告诉您@state_turns[ state.id ]不是您认为的那样。 这样,您可以更早地纠正错误,成为更有效的程序员。 此外,可以使用begin ... rescue ... end语句begin ... rescue ... end Rubyexception。 Rubyexception通常是非常友好和有用的对象,您应该学习如何在软件项目中定义自定义exception。

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

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

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

 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类。

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

  • @state_turns [state.id] .to_i> 0
  • state_a = state.auto_removal_timing.to_i + 1