【问题标题】:Pass method name as parameter to another method将方法名称作为参数传递给另一个方法
【发布时间】:2016-10-06 21:41:19
【问题描述】:

我想将方法​​名而不是块作为参数传递给另一个方法以用作回调:

def one(param)
  puts param
end

def two(param, &callback)
  callback.call(param)
end

two('hi', :one)

这可能吗?我试了一下,得到一个错误,说我传递了两个参数,但只需要一个。

【问题讨论】:

  • 预期只有一个,因为 &callback 不是参数。

标签: ruby


【解决方案1】:

如果您想发送方法的 name,那么,是的,符号是正确的形式,正如 John 的回答所指出的那样(然后您可以使用 send 调用该方法)。但是,如果您愿意,您也可以发送方法本身

def one(param)
  puts param
end

def two(param, &callback)
  callback.call(param)
end

one_method = method(:one)
two('hi', &one_method)

这种做事方式的优点是,当一个方法需要一个块时,您可以这样做,而无需(如two 所做的那样)而无需更改方法定义。您还可以传入来自不同对象的方法,而使用 send 如果您想在不同的对象上调用该方法,您还必须传入您想要调用它的人(或以其他方式弄清楚):

class Foo
  def one(param)
    puts param
  end
end

class Bar
  def two(param, &callback)
    callback.call(param)
  end
end

f = Foo.new
b = Bar.new
b.two('hi') {|param| puts param } # with a block
b.two('hi', &f.method(:one)) # with a Method object

【讨论】:

    【解决方案2】:

    虽然@JohnNaegle 的回答是正确的,但我发现使用#method 是一种更优雅的方法,它返回一个Method 对象。方法对象有一个.call(*args) 方法,尽管您可以传递参数。所以,在你的例子中,它看起来像:

    def one(param)
      puts param
    end
    
    def two(param, callback)
      callback.call(param)
    end
    
    two('hi', method(:one))
    

    变化在于您通过调用Object.method(与method 相同)而不是字符串来传递对Method 实例的引用。

    如果您想传递符号而不是 Method,您可以使用以下版本的 #two

    def two_2(param, callback)
      method(callback.to_sym).call(param)
    end
    
    two_2('hi', :one)
    # Or you could also pass a string or anything that #responds_to?(:to_sym)
    two_2('hi', 'one')
    

    我建议的进一步改进是,two 可以接受多个参数传递给回调,首先列出回调,然后使用*params 接收尽可能多的参数。这是一个示例(使用上面的#one 的定义):

    def one_with_many_params(*params)
      puts params.join
    end
    
    # Improved version of two
    def two_3(callback, *params)
      callback.call(params)
    end
    
    # Improved version of two_2
    def two_4(callback, *params)
      method(callback.to_sym).call(params)
    end
    
    two_3(method(:one), 'hi') #=> "hi"
    two_3(method(:one_with_many_params), "Hi", " my ", "name", " is ", "Foo!")
    #=> "Hi my name is Foo!"
    
    two_4('one', 'Hello!') #=> "Hello!"
    two_4(:one_with_many_params, "Hi", " my ", "name", " is ", "Bar!")
    #=> "Hi my name is Bar!"
    

    【讨论】:

      【解决方案3】:

      你想使用send:

      def two(param, callback)
        send(callback, param)
      end
      

      【讨论】:

      • 请改用public_send
      猜你喜欢
      • 2018-08-08
      • 2013-07-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-21
      • 2016-12-21
      • 1970-01-01
      相关资源
      最近更新 更多