方法的调用

# 带块的方法调用
对象.方法名 (参数, ...) do |变量 1, 变量 2, ...|
    块内容
end

# 或者是如下形式
对象.方法名 (参数, ...) {|变量 1, 变量 2, ...|
  块内容
}
5.times do |i|
  puts "第 #{i} 次循环"
end

运算符形式的方法调用

  • obj + arg1
  • obj =~ arg1
  • -obj
  • !obj
  • obj[arg1]
  • obj[arg1] = arg2

方法的分类

根据接收者不同,可分为以下 3 类:

  • 实例方法
  • 类方法
  • 函数式方法

实例方法是最常用的方法,例如,几乎所有的对象都有 to_s 方法

p "10, 20, 30, 40".split(",")
p [1, 2, 3, 4].index(2)
p 1000.to_s

对象能使用的实例方法是由对象所属的类决定的

p 10.to_s
p Time.now.to_s

类方法,接收者为类

Array.new
File.open(filename)
Time.now

# 修改文件名
File.rename(oldname, newname)

# 类也有运算符形式
Array["a", "b", "c"]

没有接收者的方法,称为函数式方法

print "hello!"
sleep(10)

若在帮助文档写明关于方法的使用,使用标记法

# 类名 # 方法名
Array#each
Array#inject

# 类方法的标记法
类名.方法名
类名::方法名

方法的定义

定义方法的语法如下:

def 方法名(参数 1, 参数 2, ...)
  希望执行的处理
end
def hello(name)
  puts "Hello, #{name}"
end

hello("Ruby")

参数带默认参数

def hello(name="Ruby")
  puts "Hello, #{name}"
end

hello()
hello("Newbie")

指定多个参数

def func(a, b=1, c=2)
  ...
end

方法的返回值

方法的返回值用 return

def volume(x, y, z)
  return x * y * z
end

def area(x, y, z)
  xy = x * y
  yz = y * z
  zx = z * x
  (xy + yz + zx) * 2
end

p volume(2, 3, 5)
p volume(10, 20, 30)

p area(2, 3, 4)
p area(10, 20, 30)

在 area 中省略了 return,当省略 return 时,会以最后一个执行的表达式结果返回

定义带块的方法

def myloop
  while true
    yield
  end
end

num = 1

myloop do
  puts "num is #{num}"
  break if num > 10
  num *= 2
end

调用方法通过块传进来的处理会在 yield 定义的地方执行

参数个数不确定

参数个数不确定时,把所有的参数封装为数组

def foo(*args)
  args
end

p foo(1, 2, 3)

这种定义的方式只能在参数列表中出现一次

关键字参数

def 方法名(参数 1: 值, 参数 2: 值, 参数 3: 值, ...)
  希望执行的处理
end
def area(x: 0, y: 0, z: 0)
  xy = x * y
  yz = y * z
  zx = z * x
  (xy + yz + zx) * 2
end

p area(x: 2, y: 3, z: 4)
p area(z: 4, y: 3, x: 2)
p area(x: 2, z: 3)

使用 **变量名的形式来接收未定义的参数

def meth(x: 0, y: 0, z: 0, **args)
  [x, y, z, args]
end

p meth(z: 4, y: 3, x: 2)
p meth(x: 2, z: 3, v: 4, w: 5)

用散列传递参数

def area(x: 0, y: 0, z: 0)
  xy = x * y
  yz = y * z
  zx = z * x
  (xy + yz + zx) * 2
end

args1 = {x: 2, y: 3, z: 4}
p area2(args1)
args2 = {x: 2, z: 3}
p area2(args2)