从输入动态调用方法的更好方法是什么?

时间:2015-08-13 06:17:24

标签: ruby input metaprogramming

在根据用户输入动态调用方法时,使用case / when事物或send方法更好吗? “更好”主要基于良好的编码实践。

     input = gets.chomp
case input
when foo
    foo
when bar
    bar
end

input = gets.chomp #Where hopefully the input would be 'foo' or 'bar'
send(input)

3 个答案:

答案 0 :(得分:1)

你的措辞让这个问题难以理解。

如果我理解正确,您希望根据用户输入调用方法。另一种方法是检查每个可能的值并调用方法,另一种方法是直接使用send

首先,请注意,在您的第一个示例中,当用户输入method1时,您正在呼叫foo。如果您使用send(input),则会调用foo。所以他们并不完全一样。

您可以通过将 input->方法映射放在哈希中来实现相同的行为:

dispatch = {foo: :method1, bar: :method2}
input    = gets.chomp.to_sym
send(dispatch[input])

另外需要注意的是,原始情况下的send会调用任何传递的方法。您可以使用上面的哈希值whitelist代替DRY并检查是否存在这样的值:

send(dispatch[input]) if dispatch.key? input

<小时/> 现在回到何时使用其中一个的问题:

  1. 如果您有 2,3,5 左右的可能性,请选择明确列出它们。它会更快,更容易阅读,更容易进行静态代码分析等等。
  2. 如果您有成百上千种不同的方法,请选择send。成本超过REPL的好处。
  3. 如果动态生成允许的方法列表,则无法选择 - 使用send。例子:
    • 您希望将方法调用到给定对象,并且每次该对象都不同
    • 您希望根据用户的权限允许使用不同的方法
    • 您希望实施具有极其动态需求的BitSet或其他一些非常棒的工具
  4. 一般情况下,不要使用元编程,除非有显着的收益或者你没有其他选择。

答案 1 :(得分:0)

除非您希望您的用户能够调用方法查找链中的任何方法,包括发送可以调用的私有方法,否则将其锁定可能是有意义的并且只允许用户使用某些方法。

如果你没有指定要发送的对象(比如上面的代码),Ruby会查看self以获取该名称的方法,然后使用常规方法查找。换句话说, self 将是方法查找链中的第一个链接。如果您确实指定了一个对象,可能是您为此目的创建的对象,另一个选项可能是使用tryrespond_to?等方法。

答案 2 :(得分:0)

input = gets.chomp
if defined?(input.to_sym)
    send(input)
else
    puts "No such thing!"