ruby 方法的调用

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}]

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容