我有一些看起来像这样的代码:
if args
eval("super(#{args.join(',')})")
else
super
end
两次方法。我想移动它,以便我的代码看起来更像:
def special_method
if a
some_block do
call_super(args, super_method)
end
else
call_super(args, super_method)
end
end
def call_super(args, super_method)
if args
eval("super(#{args.join(',')})")
else
super
end
end
我需要引用我想要调用的super
(超级special_method
),因为如果我只创建一个方法call_super
并调用super
,那么而是在超类上调用call_super
。
这有什么意义吗? X_X
答案 0 :(得分:2)
除了为什么你需要它之外,这是有意义的。 super
已经传递了当前方法接收的任何参数。 super()
没有传递任何参数。如果super(*args)
为args
或args
,则[]
会传递nil
中的所有参数,或者不传递参数。
如果您确实想要执行代码当前所执行的操作(如果它们不是args
则传递nil
,但如果不是,则传递当前方法的参数)而不是我认为您想要的,你可以写args ? super(*args) : super
作为一个简短的选择(你不能把它放在另一种方法中,因为它不知道当前的参数是什么)。
(另外,您会发现在99%的案例中您认为eval
是答案,有更好的答案。)
编辑以回应评论:
如果args
为['testing', 1]
,则super(args)
将传递一个数组参数; super(*args)
传递两个参数(字符串和整数):
# a module
module Foo
def special_method
# multiple arguments in `args`
args = ['testing', 1]
super(*args)
end
end
class Bar
# fixed number of arguments (without splats):
def special_method(first, second)
puts "First parameter: #{first}"
puts "Second parameter: #{second}"
end
end
# subclass that includes the module
class Baz < Bar
include Foo
end
Baz.new.special_method
# First parameter: testing
# Second parameter: 1
(注意&#34; *args
&#34;中的多个参数没有意义,因为*args
不是变量,args
是。)
我认为混淆的原因之一是splat有两个不同但相关的角色。在方法定义中,它们将参数收集到数组中。在其他任何地方,他们将数组分发到参数列表。
require 'pp'
def foo(*args)
pp args
end
foo([1, 2]) # all the parameters (namely, the one) collected into `args`
# [[1, 2]]
foo(1, 2) # all the parameters (the two) collected into `args`
# [1, 2]
foo(*[1, 2]) # distribute `[1, 2]` to two parameters; collect both into `args`
# [1, 2]
def foo(args)
pp args
end
foo([1, 2]) # all the parameters (the one that exists) passed as-is
# [1, 2]
foo(1, 2) # all the parameters (the two) passed as-is, but method expects one
# ArgumentError: wrong number of arguments (2 for 1)
foo(*[1, 2]) # distribute `[1, 2]` to two parameters, but method expects one
# ArgumentError: wrong number of arguments (2 for 1)