处理具有可选参数后跟关键字参数列表的方法



我想将一个可选参数(任何数据类型,甚至是哈希)后跟关键字参数列表(可以为空)传递给方法。

这就是我得到的:

def my_method(subject = nil, **options)
  [subject, options]
end

在以下情况下,方法输出符合预期:

  • my_method()
    # => [nil, {}]
    
  • 一个主题

    my_method('foo')
    # => ["foo", {}]
    
  • 带有选项的文字主题

    my_method('foo', bar: 'bar')
    # => ["foo", {:bar=>"bar"}]
    
  • 作为主题的Hash,有选项

    my_method({foo: 'foo'}, bar: 'bar')
    # => [{:foo=>"foo"}, {:bar=>"bar"}]
    
  • 没有主题,只有选项

    my_method(bar: 'bar')
    # => [nil, {:bar=>"bar"}]
    

当将Hash作为主题传递且没有选项时,期望的结果是:

my_method({foo: 'foo'})
# => [{:foo=>"foo"}, {}]

但我得到以下内容;我没有得到正确的主题:

my_method({foo: 'foo'})
# => [nil, {:foo=>"foo"}]

my_method(foo: 'foo')等同于my_method({foo: 'foo'})吗?关于如何获得预期结果的任何想法?

看,你**options作为一个没有任何默认值的参数,第一个参数有默认值。所以理解以下单参数案例

每当传递单个参数时,都会尝试将其分配给第二个参数(因为第一个参数持有默认 nil),如果由于类型不匹配而失败,则分配给第一个参数。这就是my_method(4)的工作方式。

现在假设您有一个参数作为哈希传递,它匹配分配给第二个参数,那么它当然被分配给第二个参数并且第一个设置为默认 nil。

如果你想让它工作,那么你可以执行以下操作,

> my_method({sd: 4}, {})
 => [{:sd=>4}, {}]

或者你可以在传递时提供参数名称,

> my_method(subject: {sd: 4})
 => [{:sd=>4}, {}]

据我所知,这是Ruby传递参数方式的限制。它无法区分my_method({foo: 'foo'})my_method(foo: 'foo')

为什么不用这个来破解它呢?

if subject.is_a?(Hash) && options.empty?
  subject, options = nil, subject
end

这假设subject不应该是一个哈希值。

也许不是最好的答案,但你可以尝试使用关键字参数:

def my_method(subject: nil, **options)
  [ subject, options ]
end

然后

my_method(subject: {foo: 'foo'})
=> [{:foo=>"foo"}, {}]

另类:

您可以使用

my_method({foo: 'foo'}, {})

相关内容

  • 没有找到相关文章

最新更新