简体   繁体   English

Ruby:将super传递给另一种方法以有条件地执行

[英]Ruby: Pass super into another method to execute conditionally

I have some code that looks like this: 我有一些看起来像这样的代码:

 if args
   eval("super(#{args.join(',')})")
 else
   super
 end

twice in a method. 两次。 I'd like to move it so that my code looks more like: 我想移动它,以便我的代码更像:

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

I need to have a reference to the super I want to call (super special_method ), since if I just create a method call_super and call super , it calls call_super on the superclass instead. 我需要有对基准super我想打电话给(超级special_method ),因为如果我只是创造一个方法call_super并调用super ,它调用call_super在超代替。

Does any of this make sense? 这有道理吗? x_x x_x

It makes sense except for why you would ever need it. 这是有道理的,除了您为什么会需要它。 super already passes any parameters that the current method receives. super已经传递了当前方法接收的任何参数。 super() passes no params. super()传递任何参数。 super(*args) passes any params in args , or no params if args is [] or nil . super(*args)通过在任何PARAMS args ,或不PARAMS如果args[]nil

If you actually want to do what your code currently does (pass args if they are non- nil , but current method's params if not) and not what I think you wanted, you can write args ? super(*args) : super 如果您实际上想做代码当前所做的事情(如果它们不是nil ,则传递args如果不是,则传递当前方法的参数),而不是我想的那样,您可以编写args ? super(*args) : super args ? super(*args) : super as a short alternative (you can't put this in another method since it wouldn't know what the current parameters are). args ? super(*args) : super作为简短替代(您不能将其放在另一种方法中,因为它不知道当前参数是什么)。

(Also, you will find that in 99% of cases you think eval is the answer, there is a better answer.) (此外,您会发现在99%的情况下,您认为eval是答案,会有更好的答案。)

EDIT in response to the comment: 编辑以回应评论:

if args is ['testing', 1] , then super(args) will pass one parameter that is an array; 如果args['testing', 1] ,则super(args)将传递一个参数,该参数是一个数组; super(*args) passes two parameters (a string and an integer): 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

(Note that "multiple arguments in *args " does not make sense, as *args is not a variable, args is). (请注意,“ *args多个参数”没有意义,因为*args不是变量,而args是变量)。

I think one of the reasons for the confusion is the fact that splat has two different but related roles. 我认为造成混乱的原因之一是splat具有两个不同但相关的角色。 In method definitions, they collect arguments into an array. 在方法定义中,它们参数收集到数组中。 Everywhere else, they distribute an array to an argument list. 他们在其他任何地方将数组分配到参数列表。

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM