Method Arguments

方法是一个有参数,有名字并且和对象关联的代码块,对象(更确切叫法是消息的接收者)调用方法,返回方法中最后一个表达式(ruby中基本上没有语句的概念,全是表达式)的值。很多语言都区分方法和函数,方法和对象相关。在ruby中,一切都是对象,即使你定义一个全局的函数,看上去不和任何对象关联,而实际上它被严格的定义为Object类的私有方法

irb(main):012:0> def hello
irb(main):013:1> end
=> nil
irb(main):014:0> Object.private_methods.grep :hello
=> [:hello]

 

为了方便,方法的名字以小写字母开头,当然也可以用大写字母开头,但是这样会和一般的常量混,当方法名超过一个单词时,可以用下划线将它们分开。ruby的方法名中可以有各式各样的符号,+,-,×等等,你可以为任何你想到的操作符定义成方法,唯一例外的是负号和正号,得叫'+@,-@'。

 

方法的参数:
     加不加括号?加空隔不加括号,加括号不加空隔,强调是方法调用的时候加上括号,其它时候只要不出现语法问题,在明确的情况下,我想这是自由滴。
     方法的参数在方法的名字之后,ruby的方法参数有很多种形式,ruby1.8与1.9又有一些微小的差异。ruby方法参数形式主要有:一般的,有默认值的,带*号的,hash,和带&的。一般的不用说了,首当其冲最好是放在参数列表的最前面。

 

当你定义一个方法的时候,你可以为一些参数指定默值。

def prefix(s, len=1)
  s[0,len]
end
prefix("Ruby", 3)    # => "Rub"
prefix("Ruby")       # => "R"

 

#很明显参数不仅仅只是常量,可以是实例变量,也可以是有关前一参数的表达式

def suffix(s, index=s.size-1)
  s[index, s.size-index]
end

 

在ruby1.8里面,有默认值的参数只能出现在普通参数的后面,1.9放宽了这个限制,但是有默认值的参数还是必须要连在一起的,这很好理解。

irb(main):001:0> def hello(a,b,c='world',d)
irb(main):002:1> puts a,b,c,d
irb(main):003:1> end
=> nil
irb(main):004:0> hello 1,2,3
1
2
world
3
=> nil
irb(main):005:0> hello 1,2,3,4
1
2
3
4
=> nil
#不允许的情况
irb(main):006:0> def hello(a,b,c='world',d,e='unpass')
irb(main):007:1> puts a,b,c,d,e
irb(main):008:1> end
SyntaxError: (irb):6: syntax error, unexpected '=', expecting ')'
def hello(a,b,c='world',d,e='unpass')
                            ^
(irb):6: syntax error, unexpected ')', expecting $end
	from /usr/local/bin/irb:12:in `<main>'

 

带*号的参数
   有时候我们可能想要写一个可以传递任意个参数的方法,可以使用这种参数

def max(first, *rest)
  max = first
  rest.each {|x| max = x if x > max }
  max
end
max(1)       # first=1, rest=[]   
max(1,2)     # first=1, rest=[2]  
max(1,2,3)   # first=1, rest=[2,3]

 

在一个方法的参数里,不管是形参(parameter)还是实参(argument)这种参数只能有一个,在ruby1.8里,这种参数必须出现在所有的一般参数和有默认值的参数之后,但是在1.9里面,它的后面可能出现一般参数。

irb(main):001:0> def max(first,*rest,addtion)
irb(main):002:1> max=first
irb(main):003:1> puts addtion
irb(main):004:1> rest.each{|x|max=x if x>max}
irb(main):005:1> max
irb(main):006:1> end
=> nil
irb(main):007:0> max(1,2,3)
3
=> 2
irb(main):008:0> max(1,2,3,4)
4
=> 3
irb(main):009:0> max(1,2,3,4,5)
5
=> 4

#后面的一般参数分别是倒数的第一个,第二个,以此类推。

上面看到的是带*的参数为形参时*的作用,当参数是实参时,这种作用是逆向的,有点像并行赋值时*号的作用(但是他们是有区别的)

data = [3, 2, 1]
m = max(*data)   # first = 3, rest=[2,1] => 3

#Consider what happens without the *:

m = max(data)   # first = [3,2,1], rest=[] => [3,2,1]

#In Ruby 1.9, enumerators are splattable objects. To find the largest #letter in a string, for example, we could write:

max(*"hello world".each_char)  # => 'w'

 

hash形式的参数的优点是不用记住参数的顺序,当然你可以传递一个对象,相杂整就杂整

def sequence(args)
  n = args[:n] || 0
  m = args[:m] || 1
  c = args[:c] || 0
  a = []                      # Start with an empty array
  n.times {|i| a << m*i+c }   # Calculate the value of each array element
  a                           # Return the array
end

#You might invoke this method with a hash literal argument like this:

sequence({:n=>3, :m=>5})      # => [0, 5, 10]

 

#用裸hash
sequence(:m=>3, :n=>5)        # => [0, 3, 6, 9, 12]
# Ruby 1.9 的新语法,json形式,ruby语法越来越像命令了~
sequence c:1, m:3, n:5        # => [1, 4, 7, 10, 13]
#在省去参数的小括号,hash的大括号也要省去,要不然程序会把它看成一个#block
sequence {:m=>3, :n=>5}       # Syntax error!

 

参数列表中带有&:

这种参数该是放在参数列表最后面的一种参数,&的作用有点像*,在形参里把一个block=>proc,方法调用时,逆向功能。

值得一提的是在方法内部,使用 yeild调用代码块是不需要显示的在参数列表中显示的

irb(main):020:0> def test
irb(main):021:1> yield
irb(main):022:1> end
=> nil
irb(main):023:0> test {puts "hello"}
hello
=> nil

 

在你显示的用&block声明后,你还是可以通过yield来调用代码块

irb(main):029:0> def test(&block)
irb(main):030:1> block.call()
irb(main):031:1> yield
irb(main):032:1> end
=> nil
irb(main):033:0> test{puts 'hello'}
hello
hello
=> nil

 

调用一个方法时,&的作用

a, b = [1,2,3], [4,5]                     # Start with some data.
summation = Proc.new {|total,x| total+x } # A Proc object for summations.
sum = a.inject(0, &summation)             # => 6
sum = b.inject(sum, &summation)           # => 15

 

#这样就把方法的实现抽象出来了~

在ruby1.9里面,Symbol类定义了一个to_proc方法,所以我们也可以用以下的这种形式来调用代码

words = ['and', 'but', 'car']     # An array of words
uppercase = words.map &:upcase    # Convert to uppercase with String.upcase
upper = words.map {|w| w.upcase } # This is the equivalent code with a block

 Symbol#to_pro

 def to_proc
      Proc.new { |*args| args.shift.__send__(self, *args) }
 end

 

小结:总的来说,对于形参,参数的顺序是:一般的=》缺省的=》hash=》带*号的=》&block 不过不太会出现一起用到这些参数的情况。对于方法的近亲,block,lambda,proc的参数赋值和方法参数赋值是不太一样的,留到下次吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值