如果我在 Ruby 中有以下方法:
def foo(arg1, arg2 = "bar")
puts arg1
puts arg2
end
有没有办法确定用户是否在arg2
方法中传递了一个值?显然我可以添加if arg2 == "bar"
到方法中,但这并没有捕捉到用户"bar"
自己手动传递的情况。当然,我可以将默认值设置为任何用户都不会传入的默认值,但很快就会变得非常难看。
有什么优雅的地方吗?
如果我在 Ruby 中有以下方法:
def foo(arg1, arg2 = "bar")
puts arg1
puts arg2
end
有没有办法确定用户是否在arg2
方法中传递了一个值?显然我可以添加if arg2 == "bar"
到方法中,但这并没有捕捉到用户"bar"
自己手动传递的情况。当然,我可以将默认值设置为任何用户都不会传入的默认值,但很快就会变得非常难看。
有什么优雅的地方吗?
def foo(arg1, arg2 = (arg2_not_passed = true; "bar"))
puts arg1
puts arg2
puts 'arg2 was passed' unless arg2_not_passed
end
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
一种方法(不优雅但有趣)是使默认值具有唯一的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"
我有办法!假设我们想要:
def foo(arg1, arg2 = 42)
然后我们改为写:
def foo(arg1, arg2 = [42,KEY])
如果agr2 == [42,KEY]
,我们得出结论,调用方法没有传递第二个参数,在这种情况下,42
应用默认值 。如果arg2
是别的,arg2
就通过了。简单的!
我知道你在想什么:如果调用程序真的通过了[42,KEY]
怎么办?我也想通了:KEY = rand(100000000000000)
。
我想再补充一件事。我原则上反对这样做,但我知道如果我不这样做,我会收到如此多的反对票,以至于我的名声会变成负面的。所以这里是:-)
我不确定这是可能的。考虑以下:
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 的工作原理。