1、调用的方式
对象.方法名(参数1,参数2, ... ,参数n)
以对象开头,中间隔着句点,后面接着是方法名,方法名后面是一排并列的用() 括起来的参数。不同的方法定义的参数个数和顺序也都不一样,调用方法时()可以省略。
2、带块的方法调用
带块的方法的语法如下:
对象.方法名(参数, ...) do |变量1,变量2, ...|
块内容
end
do~end 这部分就是所谓的块。除do ~end 这一形式外,我们也可以用{~}将块改写为其他形式:
对象.方法名(参数, ...) { |变量1,变量2, ...|
块内容
}
3、运算符形式的方法调用
Ruby中有些方法看起来很像运算符。四则运算等的二元运算符、-(负号)等的一元运算符、指定数组、散列的元素下标的 等,实际上都是方法。
obj + arg1
obj =~ arg1
-obj
!obj
obj[arg1]
obj[arg1] = arg2
这些虽然与一般的方法调用的语法有点不一样,但我们可以将obj理解为接收者,将 arg1、arg2 理解为参数,这样一来,它们就又是我们所熟知的方法了。我们可以自由定义这种运算符形式的方法。
4、方法的分类
根据接收者种类的不同,Ruby的方法可分为3类:
实例方法
类方法
函数式方法
4.1实例方法
实例方法是最常用的方法。假设有一个对象(实例),那么以这个对象为接收者的方法就被称为实例方法
p "10, 20, 30, 40".split(",") #=> ["10", "20", "30", "40"]
p [1, 2, 3, 4].index(2) #=> 1
p 1000.to_s #=> "1000"
4.2类方法
接收者不是对象而是类本身时的方法,我们称之为类方法。
Array.new #创建新的数组
File.open("some_file") #创建新的文件对象
Time.now #创建新的Time对象
调用类方法时,可以使用::代替.。在Ruby语法中,两者所代表的意思是一样的。
4.3函数式方法
没有接收者的方法,我们称之为函数式方法。
虽说是没有接收者,但并不表示该方法就真的没有可作为接收者的对象,只是在函数式方法这个特殊情况下,可以省略接收者而已。
print "hello!" #在命令行输出字符串
sleep(10) #在指定的时间内睡眠,终止程序
函数式方法的执行结果,不会根据接收者的状态而发生变化。程序在执行print 方法以及 sleep方法的时候,并不需要知道接收者是谁。反过来说,不需要接收者的方法就是函数式方法。
5、方法的定义
def 方法名(参数,参数, ...)
希望执行的处理
end
def hello(name)
puts "Hello, #{name}."
end
hello("Ruby")
参数的默认值,是指在没有指定参数的情况下调用方法时,程序默认使用的值。定义方法时,用参数名= 值这样的写法定义默认值。
def hello(name="Ruby")
puts "Hello, #{name}."
end
hello() #省略参数的调用
hello("Newbie") #指定参数的调用
方法的返回值
我们可以用return 指定方法的返回值。
def volume(x, y, z)
return x * y * z
end
p volume(2, 3, 4) #=> 24
p volume(10, 20, 30) #=> 6000
可以省略return 语句,这时方法的最后一个表达式的结果就会成为方法的返回值。下面我们再通过求立方体的表面积这个例子,来看看如何省略return 。
这里, area方法的最后一行的 的结果就是方法的返回值。
def area(x, y, z)xy = x * y
yz = y * z
zx = z * x
(xy + yz + zx) * 2
end
p area(2, 3, 4)
p area(10, 20, 30) #=> 2200
方法的返回值,也不一定是程序最后一行的执行结果。例如,在下面的程序中,比较两个值的大小,并返回较大的值。 if语句的结果就是方法的返回值,即a > b的结果为真时,a为返回值;结果为假时,则b为返回值。
def max(a, b)
if a > b
a
else
b
end
end
p max(10, 5)
#=> 10
因为可以省略,所以有些人就会感觉好像没什么机会用到return,但是有些情况下我们会希望马上终止程序,这时return就派上用场了。用return语句改写的max方法如下所示,大家可以对比一下和之前有什么异同。
def max(a, b)
if a > b
return a
end
return b
end
#这里的return可以省略
p max(10, 5) #=> 10
如果省略return的参数,程序则返回nil。
定义带块的方法
首先我们来实现myloop 方法,它与利用块实现循环的loop 方法的功能是一样的。
def myloop
while true
yield
end
end
num = 1
myloop do
puts "num is #{num}"
break if num > 100
num *= 2
end
yield是定义带块的方法时最重要的关键字。调用方法时通过块传进来的处理会在 yield定义的地方执行。
本例的程序中没有参数,如果yield 部分有参数,程序就会将其当作块变量传到块里。块里面最后的表达式的值既是块的执行结果,同时也可以作为yield的返回值在块的外部使用。
参数个数不确定的方法
像下面的例子那样,通过用“变量名”的形式来定义参数个数不确定的方法,Ruby就可以把所有参数封装为数组,供方法内部使用。
def foo(*args)
args
end
p foo(1, 2, 3) #=> [1, 2, 3]
至少需要指定一个参数的方法可以像下面这样定义:
def meth(arg, *agrs)
[arg, args]
end
p meth(1) #=> [1, []]
p meth(1, 2, 3) #=> [1, [2, 3]]
所有不确定的参数都被作为数组赋值给变量args。“*变量名”这种形式的参数,只能在方法定义的参数列表中出现一次。只确定首个和最后一个参数名,并省略中间的参数时,可以像下面这样定义
def a(a, *b, c)
[a, b, c]
end
pa(1,2,3,4,5) #=>[1,[2,3,4],5]
p a(1, 2) #=> [1, [], 2]
关键字参数
在目前为止介绍过的方法定义中,我们都需要定义调用方法时的参数个数以及调用顺序。而使用关键字参数,就可以将参数名与参数值成对地传给方法内部使用。
def 方法名(参数 参数1的值,参数 参数2的值, ...)
希望执行的处理
end
除了参数名外,使用“参数名:值”这样的形式还可以指定参数的默认值。用关键字参数改写计算立方体表面积的 方法的程序如下所示:
def area2(x:0, y:0, z:0)
xy = x * y
yz = y * z
zx = z * x
(xy + yz + zx) * 2
end
p area2(x: 2, y: 3, z: 4)
p area2(z: 4, y: 3, x: 2)
p area2(x: 2, z: 3)
为了避免调用方法时因指定了未定义的参数而报错,我们可以使用“**变量名”的形式来 接收未定义的参数。下面这个例子的方法中,除了关键字参数x、y、z外,还定义了**arg参数。参数arg会把参数列表以外的关键字参数以散列对象的形式保存。
def meth(x: 0, y: 0, z: 0, **args)
[x, y, z, args]
end
p meth(z: 4, y: 3, x: 2) #=> [2, 3, 4, {}]
p meth(x: 2, z: 3, v: 4, w: 5) #=> [2, 0, 3, {:v=>4, :w=>5}]
关于方法调用的一些补充
把数组分解为参数
将参数传递给方法时,我们也可以先分解数组,然后再将分解后的数组元素作为参数传递给方法。在调用方法时,如果以“*数组”这样的形式指定参数,这时传递给方法的就不是数组本身,而是数组的各元素被按照顺序传递给方法。但需要注意的是,数组的元素个数必须要和方法定义的参数个数一样。
def foo(a, b, c)
a+b+c
end
p foo(1, 2, 3) #=> 6
args1 = [2, 3]
p foo(1, *args1) #=> 6
args2 = [1, 2, 3]
p foo(*args2) #=> 6
把散列作为参数传递
我们用 这样的形式来表示散列的字面量(literal)。将散列的字面量作为参数传递给方法时可以省略 。
def foo(arg)
arg
end
p foo({"a"=>1, "b"=>2})#=> {"a"=>1, "b"=>2}
p foo("a"=>1, "b"=>2)#=> {"a"=>1, "b"=>2}
p foo(a: 1, b:2)#=> {:a=>1, :b=>2}
当虽然有多个参数,但只将散列作为最后一个参数传递给方法时,可以使用下面的写法:
def bar(arg1, arg2)
[arg1, arg2]
end
p bar(100, {"a"=>1, "b"=>2})#=> [100, {"a"=>1, "b"=>2}]
p bar(100, "a"=>1, "b"=>2)#=> [100, {"a"=>1, "b"=>2}]
p bar(100, a: 1, b: 2)#=> [100, {:a=>1, :b=>2}]
网友评论