Ruby面向对象编程中类与方法的基础学习

2019-09-25 09:37:08王振洲

有了这个黑魔法之后,以后,就可以多个相似方法中不同的部分抽出来作为参数,然后,使用一个方法定义搞定所有的方法。

method_missing()方法
Ruby是动态语言,编译器并不会检测方法调用时的行为,因此你可以调用一个不存在的方法。 在运行时,所有找不到对应方法的调用都会调用一个method_missing()方法,该方法定义在Kernal模块中,因此每个对象都继承了该方法。在kernal中method_missing()方法,会抛出一个NoMethodError的异常,这就是编译器所做的工作。

但是,我们可以覆写这个方法,让它变得很有意思。比方说,创建一个Struct,当你想要新的属性时,只需要给它赋个值就神奇的产生了。

class MyStruct  
def initialize  
@attributes = {}  
end  
 
def method_missing(name, *args)  
attribute = name.to_s  
if attribute =~ /=$/  
@attributes[attribute.chop] = args[0]  
else  
@attributes[attribute]  
end  
end  
end  
s = MyStruct.new  
s.weibo = "@xianlinbox"  
puts s.weibo       # => @xianlinbox 

这种,从调用者角度看,跟普通方法没什么区别,但是实际接收者却并没有相对应的方法的方法,Ruby术语称之为幽灵方法(Ghost Method)。对于幽灵方法,除了自定义该方法以外,还可以把该方法转发给另外一个对象的方法,当然,你可以在转发前后包装一些自己的逻辑,这种处理技术称之为动态代理(Dynamic Proxy),和前面提到的动态调用异曲同工。

使用了method_missing处理幽灵方法后,所有不存在方法的调用都会到这里来,这可能会导致一些错误信息不直观的问题(你看不到NoSuchMethod这样的提示了),因此, 在使用method_missing方案的时候,一定要限定其使用范围,并且调用父类的super.method_missing方法,让不属于这个范围的,该报什么错还是报什么错。

白板类与保留方法
每一个类都有从父类继承下来的一堆方法,在使用动态代理技术时,如果一个幽灵方法和真实的方法(你没有意料到的继承来的方法)发生名字冲突时,后者会获胜,从而导致系统报错。因此在使用动态代理技术时, 可以在代理类中删除绝大多数继承来的方法,避免发生名字冲突,删除了继承方法的类,就是所谓的白板类(Blank Slate),删除类方法的途径有2个,一个是调用Module#undef_method方法,一个是调用Module#remove_method方法。

在Ruby的Object类中,有一些方法是内部使用的,如果对其重新定义,或删除,可能导致Ruby莫名其妙的挂掉,为了防止这种事情的发生,Ruby在这些方法名前面用“__”打头,这些方法称之为保留方法,当你试图修改这些方法时,Ruby会给出警告。