0

我正在使用 Ruby 1.9.2-p180。以下代码会引发错误:

“test.rb:20:in `': main:Object (NameError) 的未定义局部变量或方法 `val'”

有没有办法让猴子修补工作返回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对名为in的方法的完全不相关的方法调用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 回答