动态方法:
(1)当调用一个对象的方法时,实际上是给一个对象发送了一条消息,ruby中Object#send()方法是,对方法调用本质的诠释,例:
obj.me_method(3) #与 obj.send(:my_method, 3)等价
使用send()方法调用方法,方法名可以成为一个参数,即可以动态的调用方法,这种技术叫做动态派发
(2)可以利用Module#define_method()方法定义一个方法,结合Object#send()既可以动态的定义方法,大量减少重复代码
幽灵方法:
(1)method_missing()是一个kernel方法,当解释器找不到对象调用的方法时,就会调用method_missing()方法,所以可以通过重写method_missing()方法来使用幽灵方法
(2)幽灵方法存在一些需要注意的地方:
幽灵方法并不是实际存在的方法,所有 respond_to?()方法会返回false,所以在使用幽灵方法时最好也重写respond_to?()方法,同时,methods()等一些列出方法名的方法返回结果中并不会有幽灵方法
幽灵方法相对于正常的方法响应时间更长,由于在方法查找时会将整个祖先链走完,才能在最后调用method_missing()方法
幽灵方法可能会和一个真实的方法名冲突,这时是调用不到幽灵方法的,可以Module#undef_method()方法,他会删除所有的(包括继承来的)方法,或者使用Module#remove_method()方法,它只会删除接受者自己的方法。最好的方式还是使用白板类
当重写method_missing()的代码中出现调用没有定义的方法,会造成死循环。
(3)幽灵方法示例:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class
MyOpenStruct
def
initialize
@attributes
= {}
end
def
method_messing(name, *args)
attributes = name.to_s
if
attributes =~ /=$/
@attributes
[attribute.chop] = args[
0
]
else
@attributes
[attribute]
end
end
end
icecream = MyOpenStruct.
new
icecream.flavor =
"vanilla"
icecream.flavor
(4)除了Object#method_missing()方法,还有Module#const_missing()方法,当引用一个不存在的常量时,会被调用
(5)方法查找时,先找到接收者的类,再沿着父类向上查找(忽略eigenclass的情况下),由于图已经比较乱了,Class类的class箭头没有给出,Class.class #=> Class