赞 | 13 |
VIP | 118 |
好人卡 | 28 |
积分 | 12 |
经验 | 35779 |
最后登录 | 2017-7-6 |
在线时间 | 1564 小时 |
Lv3.寻梦者
- 梦石
- 0
- 星屑
- 1175
- 在线时间
- 1564 小时
- 注册时间
- 2008-7-30
- 帖子
- 4418
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
本帖最后由 DeathKing 于 2010-7-21 08:43 编辑
这个东西估计你看了也没用,很少人的工程中能用上这些东西。不过你必须承认,有了这些东西,可以使方法更具有弹性,更加灵活。
另外,欢迎大家丢砖指正。测试环境是Ruby1.8.1(RGSS),RGSS2也完全可以,甚至于Ruby1.9.6也能成功运行本次范例。
一、迭代
迭代允许我们执行由我们传递的一个语句块,当然,使用关键字yield。- def a_yield_method
- yield
- end
复制代码 调用a_yield_method {p "hi! I am a yield-method."},由花括号扩住的正是我们所谓的“语句块”。事实上,你可以把一对{}替换为do~end,这似乎只关乎美观和“结合能力”的问题。- a_yield_method {p "hi! I am a yield-method."}
- #=> "hi! I am a yield-method."
复制代码 这样做有个严重的问题,当我们没有传递块的时候,会触发LocalJumpError。Kernel模块提供了一个完美的解决办法,block_given?返回true或flase来标识是否传递了一个块。于是我对上一个方法稍作修改:- def a_yield_method
- if block_given?
- yield # 如果传递了块就迭代
- else
- p "Miss" # 没传递就显示丢失
- end
- end
复制代码 这样就可以确保万无一失,同时yield关键字可以让我们对原方法随时扩容,这是否又是得益于Ruby的强动态性呢?
二、块参数
在参数前加一个&,让他变成块参数,使得他可以接受Proc对象。值得一提的是,这里的&可不是C语言里面的取址运算符。- def a_proc_method( &proc )
- p proc.class
- yield if block_given?
- proc.call if block_given?
- end
- a_proc_method
- #=> NilClass
- a_proc_method { p "Double Kill" }
- #=> Proc
- #=> "Double Kill"
- #=> "Double Kill"
复制代码 这个例子很容易理解,我们利用反射机制检测着proc参数,并且如果传递了块就迭代并调用proc的call方法(由Proc类提供)。
三、参数列表
参数前加(一元)星号,是他称为参数列表(可变参数)。可变参数是一个数组对象,应该在定义方法时置于最后,并且没有默认值。可以用for关键字或者each(Array类提供)等方法遍历参数。
展望:Ruby 2.0以上的版本中,将添加**二元星号(作用貌似是可变参数,但是一个Hash对象?)。- def multiple_arg_method( *args )
- args.each do |e|
- p e
- end
- end
- multiple_arg_method(1,"2",3.0,[4,5],{6=>7},Proc.new{p "hi"})
- #=> 1
- #=> "2"
- #=> 3.0
- #=> [4,5]
- #=> {6=>7}
- #=> #<Proc>
复制代码 方法内部,我采取的策略是使用each方法迭代每一个元素,并用p给输出出来。可以想象,我们利用可变参数做一个简单的加法方法:- def sum( *args )
- result = 0
- args.each do |e|
- result += e
- end
- return result
- end
- p sum(1,2,3,4,5,6,7,8,9)
- #=> 45
复制代码 四、活用反射机制
众所周知,向量可以于一个数量相乘,亦可以于一个向量相乘,因此,我们可以利用反射机制定义一个智能的方法,辨识传递的参数,并作出智能的部署:
在本例中,假设向量是由Vector类管理,数量是由Numeric类管理。我们在Vector类里重载*运算符,向量的x,y坐标以@x,@y这两个实变量的形式存储。- def *( opt )
- if opt.is_a? Numeric # 是数量
- self.x *= opt
- self.y *= opt
- return self
- elsif opt.is_a? Verctor # 是向量
- return self.x * opt.x + self.y * opt.y
- end
- end
复制代码 很明显,我们利用is_a?方法,判定传递过来的参数是那个类的实例,从而决定改如何操作,这的确让方法变得灵活。当然也可以用.kind_of?或者.class.ancestors.include?方法来确定。
五、参数默认值
我们可以给参数制定默认值,当没有传递参数时,这使得Ruby不会发生ArgumentError。- class Human
- attr_reader :age
- def initialize( age = 0)
- @age = age
- end
- end
- guest = Human.new
- p guest.age #=> 0
复制代码 没有传递参数,也可以正常使用?真是莫大的方便
为什么有此文?晚上睡不着觉起来蛋疼…… |
|