【问题标题】:Dynamically defined setter method is not called from block不从块中调用动态定义的 setter 方法
【发布时间】:2014-04-10 06:07:11
【问题描述】:

我一直在编写 DSL,并且正在尝试获取一个动态定义的方法,以便从 lambda 访问。除非您尝试执行 setter something=,否则这很好用,在这种情况下,lambda 调用只是设置了一个局部变量。

一个简化的例子:

class Caller
  attr_accessor :cmd
  def callme
    self.class.send(:define_method, "something") { puts "Retrieve Something" }
    self.class.send(:define_method, "something=") {|val| puts "Set Something = #{val}" }
    instance_exec &cmd
  end
end

c = Caller.new
c.cmd = lambda { something = 1 }
c.callme

如果我使用self.something=,这也可以正常工作。然而,在 DSL 的情况下,这并不理想。

如果方法前面没有self.,是否可以让它工作?

【问题讨论】:

    标签: ruby lambda metaprogramming dsl


    【解决方案1】:

    这与块或动态定义的方法完全无关。这只是简单的基本 Ruby 语法:

    foo = bar
    

    是局部变量赋值。总是。

    self.foo = bar
    

    是一个方法调用。

    如果方法前面没有self.,是否可以让它工作?

    没有。

    这只是基本的 Ruby 语法。 define_method 元编程,instance_exec,您的代码示例中的块只是一个红鲱鱼,这个问题可以用一个 更简单的例子来说明:

    def foo=(*)
      puts 'I was called!'
    end
    
    foo=('bar') # even removing spaces and adding parentheses won't help!
    
    self.foo = 'bar'
    # I was called!
    

    还要注意 foo=private 但实际上是使用显式接收器调用的(这对于 private 方法是非法的)。这是private 方法规则中的setter 方法的一个特殊例外,因为否则根本无法调用它们,正是因为它们总是会被解释为局部变量赋值。

    【讨论】:

      猜你喜欢
      • 2011-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多