【问题标题】:Using instance_exec and converting a method to a Proc使用 instance_exec 并将方法转换为 Proc
【发布时间】:2013-04-27 02:45:57
【问题描述】:

我可以获取一段代码,instance_exec,并得到正确的结果。我想从另一个对象中取出一个方法,并在我的范围内调用其中一个方法。当我从不同的对象中获取方法时,将其转换为 proc,然后 instance_exec 它,我没有得到预期的结果。代码如下。

class Test1
    def ohai(arg)
        "magic is #{@magic} and arg is #{arg}"
    end
end

class Test2
    def initialize
        @magic = "MAGICAL!"
    end

    def scope_checking
        @magic
    end

    def do_it
        ohai = Test1.new.method(:ohai)
        self.instance_exec("foobar", &ohai)
    end
end

describe "Test2 and scopes" do
    before do
        @t2 = Test2.new
    end

    it "has MAGICAL! in @magic" do
        @t2.scope_checking.should == "MAGICAL!"
    end

    # This one fails :(
    it "works like I expect converting a method to a proc" do
        val = @t2.do_it
        val.should == "magic is MAGICAL! and arg is foobar"
    end

    it "should work like I expect" do
        val = @t2.instance_exec do
            "#{@magic}"
        end

        val.should == "MAGICAL!"
    end
end

【问题讨论】:

    标签: ruby metaprogramming ruby-1.8 ruby-1.8.7


    【解决方案1】:

    似乎,在 Ruby 中,使用 def some_method 定义的方法永久绑定到定义它们的类。

    因此,当您对它们调用 .to_proc 时,它们会保留其原始实现的绑定,并且您无法重新绑定它们。好吧,您可以,但仅限于与第一个对象相同类型的对象。有可能我可以对继承做一些花哨的事情,但我不这么认为。

    解决方案变成而不是使用方法,我只是将实际的Procs 放入变量中然后使用它们,因为它们直到执行时才被绑定。

    【讨论】:

      【解决方案2】:

      不确定这是一个多么好的想法,但它通过了您的测试:

      class Test1
        def ohai(arg, binding)
          eval('"magic is #{@magic} "', binding).to_s + "and arg is #{arg}"
        end
      end
      
      class Test2
        def initialize
          @magic = "MAGICAL!"
        end
      
        def scope_checking
          @magic
        end
      
        def get_binding
          return binding()
        end
      
        def do_it
          self.instance_exec(get_binding) {|binding| Test1.new.ohai("foobar", binding) }
        end
      end
      

      【讨论】:

      • 是的,我宁愿避免使用 eval。我可以改用代码块,这样效果更好。
      猜你喜欢
      • 1970-01-01
      • 2013-04-18
      • 2011-02-26
      • 2017-04-05
      • 1970-01-01
      • 1970-01-01
      • 2019-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多