好的,我有以下代码

 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>

错误的原因是什么? 为什么将>视为一种方法,但它是逻辑运算符?

最佳答案



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



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

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

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

为了进一步扩大讨论范围,让我们看一下错误的出处。当您编写像nil > 10这样的表达式(实际上就是nil.>( 10 ))时,Ruby开始在#>的查找链中搜索nil方法。您可以通过键入以下内容查看查找链:
    nil.singleton_class.ancestors #=> [NilClass, Object, Kernel, BasicObject]

该方法将在祖先链的每个模块中进行搜索:首先,Ruby将检查是否在#>上定义了NilClass,然后在Object上定义了Kernel,然后在BasicObject上定义了,最后是#>。如果未在其中找到method_missing,则Ruby将继续尝试method_missing方法,以在查找链的所有模块上再次按顺序进行。如果即使:>也不处理NoMethodError消息,也会引发#method_missing异常。为了演示,让我们通过插入自定义消息而不是Object来在NoMethodError中定义Exception方法:
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!



Ruby中没有这样的异常(exception)。检查Ruby的 ojit_code 类。

关于ruby - 未定义的方法 '>'为nil:NilClass <NoMethodError>,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19751427/

10-11 15:05