【问题标题】:How can I reference parameters of an Object within a passed block?如何在传递的块中引用对象的参数?
【发布时间】:2018-01-02 11:31:05
【问题描述】:

我正在尝试引用与它一起传递的块内的对象的参数之一。

def command(attributes = {}, &block)
    yield
end

command(attr_1: 'Open Mike Night', 
    attr_2: 2033392,
    attr_3: [9.29, 10.08, 12.32]) do |event|

    event.message.delete

    puts "#{self.attributes[:attr_1]}" # <-- That didn't work.

end

这样的事情可能吗?如果可以,我将如何去做?我应该调查什么?

【问题讨论】:

  • 最后一个键应该是attr_3吗?
  • @sagarpandya82 你说得对,对不起!
  • 您的command 定义中有yield 吗?
  • @sagarpandya82 是的。再次抱歉,我没有添加。

标签: ruby oop metaprogramming


【解决方案1】:

让他们服从:)

def command(attributes = {})
  yield self, attributes
end

attributes = { attr_1: 'Open Mike Night', attr_2: 2033392, attr_3: [9.29, 10.08, 12.32] }

command(attributes) do |obj, attrs|
  p "#{obj.object_id}, #{attrs[:attr_1]}"
end 
# => "70309890142840, Open Mike Night"

方法范围内可用的任何方法、常量或变量都可以作为yield 的参数提供,以作为块变量发送到块中。然后,您可以随心所欲地使用它。在这种情况下,attrs 也将是一个完全可选的变量,没有它,块也是有效的。

command(attributes) { |obj| p obj.object_id } # => 70309890142840

附:如果您使用yield,则方法签名中不需要&amp;block。您也没有在问题中给yield 一个参数,而是将|event| 变量传递到块中,这本来是nil。所以我只是在上面的例子中忽略了它。

【讨论】:

    【解决方案2】:

    在我的脑海中,你可以做这样的事情。需要注意的是,我不知道这是否适合生产代码。

    此代码通过迭代参数散列的键为每个键创建实例变量。那么当我们调用command时,我们可以使用对应的instance_variable来引用block中每个key的值:

    def command(attributes = {}, &block)
      attributes.each_key { |key| 
        instance_variable_set("@#{key}",attributes[key])
      }
      yield
    end
    
    command(attr_1: 'Open Mike Night',
            attr_2: 2033392,
            attr_3: [9.29, 10.08, 12.32]) do |event|
    
      puts "#{@attr_1}"
    end
    

    打印:

    Open Mike Night
    

    【讨论】:

    • 如果方法定义在与调用位置不同的范围内,则此方法不起作用。该块由其周围环境限定,因此如果commandclass A 中定义但在class B 中调用该方法,则@attr_1 将在B 的上下文中评估,而不是A
    猜你喜欢
    • 2016-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多