这个问题是关于 Ruby 2.2 的。
假设我有一个采用位置和命名参数的方法。
class Parent
def foo(positional, named1: "parent", named2: "parent")
puts positional.inspect
puts named1.inspect
puts named2.inspect
end
end
子类既要覆盖一些默认值,又要添加自己的命名参数。我将如何最好地做到这一点?理想情况下,它不必知道父签名的详细信息,以防父想要添加一些可选的位置参数。我的第一次尝试是这样的。
class Child < Parent
def foo(*args, named1: "child", named3: "child" )
super
end
end
但这会爆炸,因为未知数named3:
已传递给父级。
Child.new.foo({ this: 23 })
/Users/schwern/tmp/test.rb:10:in `foo': unknown keyword: this (ArgumentError)
from /Users/schwern/tmp/test.rb:15:in `<main>'
我尝试将参数显式传递给 super,但这也不起作用。似乎第一个位置参数被视为命名参数。
class Child < Parent
def foo(*args, named1: "child", named3: "child" )
super(*args, named1: "child")
end
end
Child.new.foo({ this: 23 })
/Users/schwern/tmp/test.rb:10:in `foo': unknown keyword: this (ArgumentError)
from /Users/schwern/tmp/test.rb:15:in `<main>'
我可以让 Child 知道第一个位置参数,它有效......
class Child < Parent
def foo(arg, named1: "child", named3: "child" )
super(arg, named1: "child")
end
end
Child.new.foo({ this: 23 })
Parent.new.foo({ this: 23 })
{:this=>23}
"child"
"parent"
{:this=>23}
"parent"
"parent"
...直到我传入一个命名参数。
Child.new.foo({ this: 23 }, named2: "caller")
Parent.new.foo({ this: 23 }, named2: "caller")
/Users/schwern/tmp/test.rb:10:in `foo': unknown keyword: named2 (ArgumentError)
from /Users/schwern/tmp/test.rb:15:in `<main>'
如何进行这项工作并保留命名参数检查的好处?我愿意将位置参数转换为命名参数。