在ruby中定义方法时,传入参数的方式是非常灵活的,今天总结下ruby中的参数类型和一些使用方法:

1. 必选型参数(Required Arguments)

def info(name, age)
  puts "#{name} is #{age} years old."
end

这样当你调用该方法时必须同时传入两个方法

info("allen", 25)
#=> allen is 25 years old.

2. 可选型参数(Optional Arguments)

def info(name, age, score=99)
  puts "#{name} is #{age} years old and scored #{score}"
end

info('allen', 25, 50)
#=> allen is age years old and scored 50
#说明: 参数name是"allen",  age是25, score是50

info('allen', 25)
#=> allen is 25 years old and scored 99
#说明: 参数name是"allen",  age是25, score是默认值99

3. 变量型参数(Variable Arguments), 这种形式允许传0或多个参数,即使调用时忘记传参ruby也不会报错,传入的参数会被放到一个数组中,形式是参数前面加一个*.

  def method(*arg)
    puts arg.inspect
  end

这样你在调用方法的时候可以传入任何数量和类型的参数,包括none。即如果调用method时不传入参数,p表示一个空数组。如果传入多个参数,那么参数的值就是包含这些参数的数组。

  method   # puts []
  method(1,2,3)  # puts [1, 2, 3]
  method('tom', age: 25) # puts ["tom", {:age=>25}]

如果调用method时不传入参数,p表示一个空数组。如果传入多个参数,那么参数的值就是包含这些参数的数组。

4. hash型参数(Keyword Arguments),该类型使用**arg双星号表示

  def method(**arg)
    puts arg.inspect
  end
  method  #puts {}
  method(age: 3, name: "tim") # puts {:age=>3, :name=>"tim"}

5. block参数,该类型使用&block表示,&block是传入该方法中的block对象的一个引用

  def method(a, &block)
    "a: #{a}, block: #{block}"
  end
  method(2) #=> "a: 2, block: "
  method(2){ 5 + 5 } #=> "a: 2, block: #<Proc:0x007ff8e088b8b0@(irb):14>"

上面显示block为一个Proc对象,我们调用Proc的call方法看下:

  def method(a, &block)
    "a: #{a}, block: #{block.call(100)}"
  end
  method(2){ 5 + 5 } #=> "a: 2, block: 10"
  method(2){|x| x + 5 } #=> "a: 2, block: 105" 这里call方法将100传入到block中并参与计算

上面介绍了几种种参数形式,而实际的使用中多是混合使用这些参数的,我们找几个例子分析一下.

首先尝试下最简单的混合方式,必选参数 + 可选参数

  def mix_method(a, b, *p)
  end

  mix_method(1,2)     #参数对应值 a =>1, b => 2, p => []
  mix_method(1,2, 3)   #参数对应值 a =>1, b => 2, p => [3]

现在我们定义一个参数复杂些的方法,包含无规则顺序的必选和可选参数

  def mix_method(a, b, *p, q)
    "a is #{a}, b is #{b}, p is #{p}, q is #{q}"
  end

  #我们调用这个方法时可以传入3或者3个以上的参数,这种情况下必选参数会优先被指定,如果还有剩余的值会以数组的形式指定给可选参数

  mix_method(1,2,3)   #=> "a is 1, b is 2, p is [], q is 3"
  mix_method(1,2,3,4) #=> "a is 1, b is 2, p is [3], q is 4"
  mix_method(1,2,3,4,5) #=> "a is 1, b is 2, p is [3, 4], q is 5"

包含必选,可选和默认值的参数

  def  mix_method(a, b, c=100, *p, q)
    "a is #{a}, b is #{b}, c is #{c}, p is #{p}, q is #{q}"
  end

  #同样该方法可以传入3个和3个以上的参数

  mix_method(1,2,3)   #=> "a is 1, b is 2, c is 100, p is [], q is 3"
  mix_method(1,2,3,4) #=> "a is 1, b is 2, c is 3, p is [], q is 4"
  mix_method(1,2,3,4,5) #=> "a is 1, b is 2, c is 3, p is [4], q is 5"
  mix_method(1,2,3,4,5,6) #=> "a is 1, b is 2, c is 3, p is [4, 5], q is 6"

通过上面的几个例子证明了ruby中定义方法参数的灵活性,但是定义方法时有一个准则必须遵守,那就是可选参数不能定义在带有默认值的参数之前,如:

  def mix_method(a, b = 5, *p)   #正确
  def mix_method(a, *p, b = 5)   #错误,会报一个语法错误

所以正确的传参顺序为: required -> optional -> variable -> keyword -> block