那里的 Ruby 书籍详细解释了这一点。但即使没有,你也会习惯它的逻辑。一个体面的编码器首先定义具有强制性有序参数的函数,如下所示:
def foo( a, b, c=0, d=0 )
# ...
end
简单地说,前 2 个 args 转到a
, b
,然后最多 2 个可选 args 到c
, d
, 。但是你被授予了超越一般体面的自由:
def foo( a=0, b )
# ...
end
如果您提供 1 个参数,它将转到b
. 如果您提供 2 个参数,它们将按顺序分配给a
, b
, 。这不太体面,因为它需要从用户那里学习更多。如果您自己是用户,那么您就是对自己不雅,但仍然没有语法歧义。现在看看这个:
def foo( a=0, b, c=0 )
# ...
end
如果你打电话foo( 1, 2 )
,你的意思是a = 1
, b = 2
, c = 0
, 还是a = 0
, b = 1
, c = 2
? 也许第一个更有可能,但编码的规则是,不要猜测用户的意图。因此,Ruby 团队可能决定不纵容这种语法。您仍然可以通过定义:
def foo( *args )
a, b, c = case args.size
when 1 then [0, args[0], 0]
when 2 then [*args, 0]
when 3 then args
else fail ArgumentError; "#{args.size} arguments for 1..3!" end
# ...
end
因此,事实上,你被赋予了绝对的自由,但是 Ruby 会引导你进行良好的实践:让好代码看起来比坏代码更好看。同样适用于使用 * splat 收集参数。体面的案例是明确的:
def foo( a, b=0, *c )
# ...
end
但是有:
def foo( a=0, b, *c )
# ...
end
当你打电话时foo( 1, 2, 3 )
,你的意思是a = 1
, b = 2
, and c = [3]
, or a = 0
, b = 1
, andc = [2, 3]
吗?因此,同样,不鼓励第二种情况,但仍然可以实现:
def foo( *c )
a, b = case c.size
when 0 then fail ArgumentError, "Too few arguments!"
when 1 then [0, c.shift]
else [c.shift, c.shift] end
# ...
end
编写具有许多参数的函数,尤其是具有许多有序参数的函数是不好的做法。有句老话,二元比三元好,一元比二元好,最后,零比一元好。如果你的方法需要很多参数,你应该用一个 object 替换它来重构它。这回答了你的问题了吗?