如果我在Ruby中使用以下方法:
def foo(arg1, arg2 = "bar")
puts arg1
puts arg2
end
有没有办法确定用户是否在方法中传递了arg2
的值?显然我可以在方法中添加if arg2 == "bar"
,但这并不能解决用户自己手动传入"bar"
的情况。当然,我可以将默认值设置为没有用户可以传递的内容,但是很快就会变得非常难看。
那里有什么优雅的东西吗?
答案 0 :(得分:15)
def foo(arg1, arg2 = (arg2_not_passed = true; "bar"))
puts arg1
puts arg2
puts 'arg2 was passed' unless arg2_not_passed
end
答案 1 :(得分:3)
def foo(*args)
case args.length
when 1
# arg2 was not given
arg1, arg2 = args.first, "bar"
...
when 2
# arg2 was given
arg1, arg2 = args
...
else
raise ArgumentError
end
end
答案 2 :(得分:3)
一种方式(不优雅但有趣)是使默认值具有唯一object_id
。如果默认值是一个像整数这样的不可变对象,那么它将不起作用。
def c
@c ||= "bar"
end
def fun(a,b = c)
puts b.object_id == c.object_id ? "default" : "user"
end
fun "foo"
#=> "default"
fun "foo", "bar"
#=> "user"
答案 3 :(得分:2)
我有一个解决方案!假设我们想:
def foo(arg1, arg2 = 42)
然后我们会写:
def foo(arg1, arg2 = [42,KEY])
如果agr2 == [42,KEY]
,我们得出结论,调用方法没有传递第二个参数,在这种情况下,默认值42
适用。如果arg2
是其他内容,则arg2
已通过。简单!
我知道你在想什么:如果调用程序实际通过了[42,KEY]
怎么办?我也想到了这一点:KEY = rand(100000000000000)
。
我想补充一点。我原则上反对这样做,但我知道如果我不这样做,我会收到这么多的支持,我的名声将会消极。所以这里是: - )
答案 4 :(得分:1)
我不确定这是可能的。请考虑以下事项:
class Test
def method(a,b=1)
local_variables.each do |var|
puts "Setting #{var} to #{eval var.to_s}"
end
end
end
然后尝试在method
Test
?> t.method(1)
Setting a to 1
Setting b to 1
=> [:a, :b]
?> t.method(1,2)
Setting a to 1
Setting b to 2
=> [:a, :b]
?> t.method(1,1)
Setting a to 1
Setting b to 1
=> [:a, :b]
那些不区分方法的调用方式。
所以我建议@ sawa的方法与以下内容混合:
raise ArgumentError, "Too many arguments" if args.length > 2
因为您似乎想要将参数限制为2,而@ sawa的方法允许使用未定义的数字。
这是针对非正统要求的非正统方法,因此请确保您方法的客户了解API的工作原理。