【问题标题】:Reflection on method parameters in RubyRuby 中方法参数的反思
【发布时间】:2010-08-11 09:00:07
【问题描述】:

参加以下课程:

class Automator
  def fill_specific_form(fields)
    fields.each_pair do |key, value|
      puts "Setting '#{key}' to '#{value}'"
    end
  end
end

a = Automator.new
a.fill_specific_form :first_name => "Mads", :last_name => "Mobæk"

# => Setting 'first_name' to 'Mads'
# => Setting 'last_name' to 'Mobæk'

是否可以在没有哈希的情况下做同样的事情?由于所有参数都是必需的,我想要一个具有以下签名的方法:

fill_specific_form(first_name, last_name)

在我看来,这可以通过让方法体反射和迭代其参数来实现,从而获得相同的结果。

您将如何实现这一点?是否已经存在这种模式/习语?两个明显的好处是 IDE 中的参数信息,并且不必检查是否提供了所有哈希键。

我要避免的是:

puts "Setting first_name to #{first_name}"
puts "Setting last_name to #{last_name}"
# and so on

【问题讨论】:

标签: ruby reflection


【解决方案1】:

如果你在方法中没有设置其他局部变量,local_variables 会给你一个方法的参数名称列表(如果你设置了其他变量,你可以首先调用local_variables 并记住结果)。所以你可以用local_variables+eval做你想做的事:

class Automator
  def fill_specific_form(first_name, last_name)
    local_variables.each do |var|
      puts "Setting #{var} to #{eval var.to_s}"
    end
  end
end

Automator.new().fill_specific_form("Mads", "Mobaek")

但请注意,这是纯粹的邪恶。

至少对于你的例子

puts "Setting first_name to #{first_name}"
puts "Setting last_name to #{last_name}"

似乎更明智。

您也可以在方法的开头使用fields = {:first_name => first_name, :last_name => last_name},然后使用您的fields.each_pair 代码。

【讨论】:

  • 纯粹的邪恶不是故意的,也不是我想要的。只是好奇是否有办法做到这一点。我会测试你的建议并回复你
  • fields = {:first_name => first_name, :last_name => last_name} 是我想要的。谢谢。
  • 我尝试使用 Ruby 1.9.3,你必须做 #{eval var.to_s} 才能让它工作,否则你会得到一个 TypeError: can't convert Symbol into String
  • @JavidJamae 是的,他们在 1.9 中将 local_variables 从字符串数组更改为符号数组。
【解决方案2】:

我不太明白。你想接收单个数组中的所有参数吗?

def fill_specific_form *args
    #Process args
end

【讨论】:

  • 不完全。这只会获取传递的值。通过使用与表单元素名称匹配的显式参数名称,我可以设置 name = value。查看 sepp2k 的答案
【解决方案3】:

要反映方法的(或Proc 的)参数,您可以使用Proc#parametersMethod#parametersUnboundMethod#parameters

->(m1, o1=nil, *s, m2, &b){}.parameters
# => [[:req, :m1], [:opt, :o1], [:rest, :s], [:req, :m2], [:block, :b]]

但是,就您而言,我不明白您为什么需要反射,因为您已经知道参数的名称。

【讨论】:

  • 这是 1.9.2 中的新功能吗?这在 1.8.7 或 1.9.1 中对我不起作用。
  • @sepp2k:是的,Proc#parameters 是 1.9.2 中的新功能。
猜你喜欢
  • 1970-01-01
  • 2011-06-12
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 2016-02-05
  • 1970-01-01
  • 2011-02-14
  • 1970-01-01
相关资源
最近更新 更多