动态创建方法,包括动态但固定的参数列表,在ruby中使用define_method?

时间:2017-06-28 00:05:44

标签: ruby methods reflection

如何使用在运行时由符号数组或命名参数的固定哈希确定的固定参数列表动态创建方法?是的,我可以使用一个点运算符来接受任何参数,但是当参数不匹配运行时数组(或哈希)时,我想提出与静态情况相同的ArgumentError

静态地,我写了

 def foo(bar,baz)
   [bar,baz]
 end

 foo(1,2) #=>[1,2]
 foo(1,2,3) #=> ArgumentError: wrong number of arguments (given 3, expected 2)

现在我想在运行时创建此方法。根据{{​​3}},我们可以

 define_method(:foo) do |bar,baz|
   [bar,baz]
 end

 foo(1,2) #=> [1,2]
 foo(1,2,3) #=> ArgumentError: wrong number of arguments (given 3, expected 2)

但只有在编写方法时我知道参数列表才有效。如果在运行时只有参数列表怎么办?在define_method: How to dynamically create methods with arguments,建议我们可以使用splat运算符接受任何参数数组:

 define_method(:foo) do |*args|
   args
 end

 foo(1,2) #=> [1,2]
 foo(1,2,3) #=> [1,2,3]

但是我们可以修复允许的参数以符合运行时给出的参数列表,复制静态代码,以便发生以下情况吗?

 arr = [:bar,:baz]

 define_method(:foo) do |*args=arr| #or some other magic here
   args
 end

 foo(1,2) #=> [1,2]
 foo(1,2,3) #=> ArgumentError: wrong number of arguments (given 3, expected 2)

1 个答案:

答案 0 :(得分:0)

我能想到的一种方法是,如果参数的数量与您设置的期望不匹配,则明确检查args.countraise ArgumentError

class Foo 
  def self.create_method(method_name, number_of_arguments)
    define_method(:"#{method_name}") do |*args|
      if args.count > number_of_arguments
        raise ArgumentError, "wrong number of arguments (given #{args.count}, expected #{number_of_arguments})"
      end 

      puts "Inside #{method_name}, recevied arguments: #{args.join(", ")}"  
    end 
  end 
end

<强>输出:

Foo.create_method("yolo", 2)
Foo.new.yolo("arg1", "arg2") // Inside yolo, recevied arguments: arg1, arg2
Foo.new.yolo("arg1", "arg2", "arg3") //  wrong number of arguments (given 3, expected 2) (ArgumentError)