Friday, October 24, 2008

(1)Ruby中的方法

前面我们就已经接触到了Ruby中的方法,这一节我们将详细讲解方法的定义、调用等细节。
首先说,从语法上来讲,方法以def 关键字开头后面是方法名、0到多个参数,方法以end关键字结尾,方法的参数可以当作变量在方法体内使用。下面是一个例子:
# 定义一个名为 'factorial' 的方法,它只有一个参数 'n'
def factorial(n)
  if n < 1                # 校验参数的合法性
    raise "argument must be > 0"
  elsif n == 1            # 如果参数为 1
    1                     # 那么参数的返回值就是 1
  else                    # 否则计算阶乘
    n * factorial(n-1)    # 计算n-1的阶乘
  end
end
上面的方法只有一个参数,用于计算整数的阶乘,你可以看到这是一个递归调用的方法。
方法都有返回值,返回值就是方法的最后一个表达式的值,如果一个方法中没有表达式那么返回值就是nil。像上面的factorial方法,如果正常执行,返回值就是1或者n*factorial(n-1)。
当然,你还可以用return 关键字来强制返回一个值,这种方式一般出现在两种情况:

  1. 你需要在方法的最后一行之前返回一个值。
  2. 你的方法有多个返回值,如果有多个返回值,那么最终的返回值是一个数组。
下面是一些例子:
def factorial(n)
  raise "bad argument" if n < 1
  return 1 if n == 1
  n * factorial(n-1)
end

#返回多个值时要使用关键字return
def polar(x,y)
  return Math.hypot(y,x), Math.atan2(y,x)
end

# 将最后一行的多个表达式值,转换成一个数组就可以省略return
def cartesian(magnitude, angle)
  [magnitude*Math.cos(angle), magnitude*Math.sin(angle)]
end
这种返回多个值得方法,通常被用于平行赋值:
distance, theta = polar(x,y)
x,y = cartesian(distance,theta)

Ruby是一个完全面向对象的语言,那么所有的方法都是通过对象调用的,即使是我们在一个脚本中写的一个单一的方法,其实底层实现中它实际上是Object类的私有方法。如果你定义了一个类并在类中定义了方法,那么和其他语言类似,Ruby中对象的方法通过点号访问(.),self关键字表示调用方法那个对象本身的引用。如果你使用过Java,那么这个self相当于Java中的this。对了,还记得我们以前讲过的异常处理吗,那么说rescue要存在于begin和end块之间,如果你是在一个方法中使用rescue,可以直接放在方法体中。
前面我们给出的方法都是“全局”方法,后面我们介绍类的时候还会介绍类的方法,然而,我们还可以定义另一种方法,假如现在你有一个对象,你只想在当前这个对象上定义一个方法,那么你需要使用def关键字并且方法名是一个对象名加点号,后面再跟方法名的方式,我们称这种方法为单一方法:
o = "message"    # 一个字符串对象
def o.printme    # 为这个对象定义一个单一方法
  puts self
end
o.printme        # 调用这个方法
我们除了可以定义一个方法还可以“解除定义”一个已经存在的方法,方法是使用关键字undef:
def sum(x,y); x+y; end      # 定义一个方法
puts sum(1,2)               # 使用它
undef sum                   # 解除定义

undef并不常用,不过有一种情况可能有用,比如对于子类方法访问的限制,举个例子:类A定义了方法m,B是A的子类,那么按照继承的原则,B当然拥有方法m,但是可能出于某种原因你不希望使用B的人调用方法m,那么你可以在类B中undef m。不过通常的方式我们是通过在B中重载m的方式来完成的。对于类和模块,还有一个私有方法undef_method,你可以把你不需要的一系列方法通过它来“解除定义”。

No comments: