21

OK私は次のコードを持っています

 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 )、と解釈されます。同じことを理解する別の方法は、オブジェクトにメッセージを送信していることです。#+12[ :+, 2 ]1

エラーの原因は何ですか?

今あなたの場合、何らかの理由で@state_turns[ state.id ]返品します。nilしたがって、式は に@state_turns[state.id] > 0なります。これは、前に述べたように、メソッド onnil > 0を呼び出すと理解されます。しかし、 が属する にインスタンス メソッドが定義されていないことを確認できます。#>nilNilClassnil#>

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

したがってNoMethodError、例外は正当なエラーです。このエラーを発生させることで、Ruby はあなたを保護します。つまり、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 は、最初に#>が定義されているかどうかを確認しNilClass、次に on Object、次にKernel、最後にBasicObject. #>それらのいずれにも が見つからない場合、Ruby は引き続きmethod_missing、ルックアップ チェーンのすべてのモジュールで順番にメソッドを試行します。メッセージをmethod_missing処理しない場合でも、例外が発生します。実演するために、代わりに表示されるカスタムメッセージを挿入してメソッドを定義しましょう::>NoMethodError#method_missingObjectNoMethodError

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 に答える