我可以创建将位置和关键字参数的任意组合传递给另一种方法的方法吗?
此版本在所有情况下均不起作用:
def proxy(*args, **keywords)
send(yield, *args, **keywords)
end
def foo1(param)
puts 'foo1', param
end
def foo2(params:)
puts 'foo2', params
end
def foo3(param, params:)
puts 'foo3', param, params
end
def foo4()
puts 'foo4'
end
proxy('param') { 'foo1' } #1
proxy(params: 'params') { 'foo2' } #2
proxy('param', params: 'params') { 'foo3' } #3
proxy { 'foo4' } #4
#2和#3正在工作。
#1加注wrong number of arguments (given 2, expected 1) (ArgumentError)
#4加注wrong number of arguments (given 1, expected 0) (ArgumentError)
答案 0 :(得分:1)
您可以尝试:
def proxy(*args)
send(yield, *args)
end
[24] pry(main)> proxy('param') { 'foo1' } #1
foo1
param
=> nil
[25] pry(main)> proxy(params: 'params') { 'foo2' } #2
foo2
params
=> nil
[26] pry(main)> proxy('param', params: 'params') { 'foo3' } #3
foo3
param
params
=> nil
[27] pry(main)> proxy { 'foo4' } #4
foo4
答案 1 :(得分:0)
您在上面使用两种不同类型的参数,关键字参数和位置参数。可以在以下位置找到有关差异的很好描述:
https://robots.thoughtbot.com/ruby-2-keyword-arguments
使用他们给出的示例:
def mysterious_total(subtotal, tax, discount)
subtotal + tax - discount
end
mysterious_total(100, 10, 5) # => 105
上面是一个有效的方法,但是在调用它时,如果不查看方法本身的定义,就不会真正知道放置参数的位置。如果小计并以错误的方式计税,您将得到错误的结果。关键字参数通过说明参数名称来防止这种情况:
def obvious_total(subtotal:, tax:, discount:)
subtotal + tax - discount
end
obvious_total(subtotal: 100, tax: 10, discount: 5) # => 105
我认为这是更好的方法,尽管并非每个红宝石编码人员都同意。这样,您可以在不中断方法的情况下重新排列参数,并且无论您在何处阅读该方法都有意义。如果要使用其中一些可选功能,可以执行以下操作:
def obvious_total(subtotal: 100, tax: 10, discount: 5)
subtotal + tax - discount
end
如果您现在只调用obvious_total
而没有任何参数,它将使用您提供的默认参数,并且可以仅使用一个参数obvious_total(subtotal: 200)
进行调用
使用放置参数进行此操作要困难得多,因为代码不知道您缺少哪个参数。使用第一个示例:
def mysterious_total(subtotal = 100, tax = 10, discount = 5)
subtotal + tax - discount
end
如果我只是打电话给mysterious_total(100)
,则系统不知道我遗漏了哪个参数
最后,在同一方法定义中混合使用位置参数和关键字参数是不好的做法。进一步阅读:
https://makandracards.com/makandra/36011-ruby-do-not-mix-optional-and-keyword-arguments