言归正传。。。
刚看ruby时,看到 1+“23”这样的表达式,觉得很N(orth)B,数字跟字符居然可以这样运算。时间越久,就越想知道为什么可以这样做,具体的过程是什么样的,在rubinius之前,这个探索是痛苦的。因为ruby是用c语言实现的,而那个C语言的代码我看着实在是不习惯。比如下面的代码,直到现在也木有弄明白。哪位知道的可以给我指导一下。
static inline void rb_ary_modify_check(ary) VALUE ary; { if (OBJ_FROZEN(ary)) rb_error_frozen("array"); if (FL_TEST(ary, ARY_TMPLOCK)) rb_raise(rb_eRuntimeError, "can't modify array during iteration"); if (!OBJ_TAINTED(ary) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't modify array"); }
自从有了rubinius,又多了一条探索ruby世界奥秘的路,重要的是,这是条我比较习惯的路。好吧,还是回到1+“23”这个问题上来。
rubinius的实现中,主要用到了3个方法: :+, :redo_coerce,:math_coerce
具体如下:
def +(o) Ruby.primitive :fixnum_add redo_coerce :+,o end def redo_coerce(math,right) b,a = math_coerce(right) a.__send__ meth,b end def math_coerce(other,error = :coerce_error) begin values = other.coerce(self)#[other,self] rescue send error,other end unless values.__kind_of__(Array)&&values.length==2 do raise TypeError,"coerce must return [x,y]" end values[1],values[0] end
整个实现就差不多了,但是没完!!!注意到math_coerce这个方法的参数之一是other,而other又调用了coerce这个方法。。。。。从中看出点什么东西来没????我猜你想到了,要使1+“23”能工作,也就是说能得到24,那么应该为String类实现coerce(貌似强制的意思)这个方法。
class String def coerce(n) if self['.'] values = [n, Float(self)] print "self is ",self,"\n" [n, Float(self)] else [n, Integer(self)] end end end
这样就大功告成了。理解了这个,也就可以为其他很多的类实现运算,进而可以得到你想要的结果了。North B