【问题标题】:Issue with monkeypatching猴子补丁问题
【发布时间】:2012-07-23 16:26:25
【问题描述】:

我正在使用 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

【问题讨论】:

    标签: ruby monkeypatching


    【解决方案1】:

    直接的问题是你在第 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
    

    你有

    • inject 中未使用的方法参数 val
    • testObj.m 中名为val 的方法的完全不相关的方法调用

    如果你想访问周围的范围,你需要使用一个块。值得庆幸的是,有一个(系列)方法可以使用块并定义方法:

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

    现在,一切都按预期进行:

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

    【讨论】:

      猜你喜欢
      • 2010-11-26
      • 2011-01-14
      • 2015-08-21
      • 2016-09-01
      • 2012-09-16
      • 2012-12-18
      • 2020-01-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多