Ruby:将super传递给另一个有条件执行的方法

时间:2015-04-14 01:09:01

标签: ruby-on-rails ruby

我有一些看起来像这样的代码:

 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

1 个答案:

答案 0 :(得分:2)

除了为什么你需要它之​​外,这是有意义的。 super已经传递了当前方法接收的任何参数。 super()没有传递任何参数。如果super(*args)argsargs,则[]会传递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)