`method_missing': stack level too deep (SystemStackError)

1971 ワード

今日はmethodについて面白い話に出会った.missingのコード:
 
 
class Roulette
  def method_missing(name, *args)
    person = name.to_s.capitalize
    3.times do
      number = rand(10) + 1
      puts "#{number}..."
    end
   "#{person} got a #{number}"
  end
end

r = Roulette.new
puts r.bob

 
method_についてmissing、ancestors chainで変更方法が見つからない場合、rubyはmethod_を実行します.missingメソッド
このコードの意味はmethod_を書き換えることですmissingメソッドは、r.bobを実行するとbobメソッドが定義されていないためmethod_missing
メソッドでは、人名を大文字に変換し、3回ループしてランダム数を得ると、期待される結果は次のようになります.
 
4....
2....
7....
BOB got a 7
 
しかし実行結果はデッドサイクルであり、最後にプログラムは異常を投げ出す:`method_missing': stack level too deep (SystemStackError)
 
問題の原因はこの最後の文でnumber変数を得た:「#{person}got a#{number}」
ここでnumber変数はblokで定義されており、blokの外でnumberはすでに作用範囲を超えており、rubyは変数であることを知らず、カッコをつけない方法として呼び出され、method_が再呼び出されるmissingメソッド、このように繰り返して、死の循環になりました
 
だからblockの外でnumber=0を定義して、プログラムは正しく実行することができます
 
 
class Roulette
  def method_missing(name, *args)
    person = name.to_s.capitalize
    number = 0
    3.times do
      number = rand(10) + 1
      puts "#{number}..."
    end
   "#{person} got a #{number}"
  end
end

r = Roulette.new
puts r.bob

 
また、このようなトラブルを避けるために、ある方法を実行すると、どのように処理するか分からないので、Kernelのmethod_に戻ることを覚えておいてください.missingメソッド.
 
 
class Roulette
  def method_missing(name, *args)
    person = name.to_s.capitalize
    super unless %w[Bob Frank Bill].include?(person)
    number = 0
    3.times do
      number = rand(10) + 1
      puts "#{number}..."
    end
   "#{person} got a #{number}"
  end
end

r = Roulette.new
puts r.bob