0

Ruby 1.9.2-p180 を使用しています。次のコードはエラーをスローします。

「test.rb:20:in `':未定義のローカル変数またはメソッド `val' for main:Object (NameError)」

モンキーパッチを機能させて元に戻す方法はありvalますか?

class Test
  def m
    "m"
  end
end

def inject(testObj, val)
  def testObj.m
    val
  end

  testObj
end


t = Test.new
puts t.m
puts inject(t, val).m
4

1 に答える 1

3

当面の問題は、20行目で呼び出していることです

puts inject(t, val).m

valつまり、引数としてに渡していますがinject、実際には を定義していませんval。たとえば、実際の値を渡す必要があります。

puts inject(t, 'Hello, World!').m

またはval最初に定義します。

val = 42
puts inject(t, val).m

ただし、これを行うと、新しいエラーが発生します。

NameError: undefined local variable or method `val' for #<Test:0x007fa1228439b8>

その理由は、Ruby ではブロックだけがクロージャーになれるからです。メソッドは、周囲のレキシカル環境を閉じません。

つまり、ここでは次のことを意味します。

def inject(testObj, val)
  def testObj.m
    val
  end

  testObj
end

あなたが持っている

  • 未使用のメソッドval引数inject
  • valで指定されたメソッドへのまったく無関係なメソッド呼び出しtestObj.m

周囲のスコープにアクセスしたい場合は、ブロックを使用する必要があります。ありがたいことに、ブロックを取り、メソッドを定義するメソッド (のファミリー) があります。

def inject(testObj, val)
  testObj.define_singleton_method(:m) do
    val
  end

  testObj
end

これで、すべてが期待どおりに機能します。

puts inject(t, 'Hello, World!').m
# Hello, World!
于 2012-07-23T16:43:27.333 に答える