最近在巩固Ruby 的基本语法知识,在这里把以前一些不知道的特性一一总结下来。
在Ruby中是允许method的重复声明的,并且在合适的时候还允许你去一个一个调用(利用super关键字)。
在这里通过几个实例,我将和大家分享一下Ruby的method查找路径和方式以及super的使用和参数问题。
首先,让大家来看看这样一个例子:
class A def a p 'a 1' end def a p 'a 2' super p 'a 2 END' end end b = A.new b.a
输出结果是:
从结果中,我们可以发现:如果在一个class里面重复声明两个同样的方法(同样的method名称和参数数目 ),原先的方法将被后面的方法完全覆盖掉(即原先的定义无效了) 。当然这是一个很正常的状况,在Java中语法直接不允许。这里虽然允许了,但是没有什么实际上面的意义。那么这里的super是什么意义呢?让我们慢慢来看。
让我们看看第二个例子:
class B def a p 'B a 1' end end class A < B def a p 'a 1' end def a p 'a 2' super p 'a 2 END' end end b = A.new b.a
输出结果:
似乎很怪异吧,这就是Ruby中super关键字的一部分作用了。其实有点像Java中的Method overwrite 然后在通过super.XXXMethod去调用祖先方法,其中执行的顺序也是类似的。例子中,我们也看到了那个原先定义在A中的a方法确实没有用了。
其实Module也有类似的效果:
module B def a p 'B a 1' end end class A include B def a p 'a 1' end def a p 'a 2' super p 'a 2 END' end end b = A.new b.a
输出结果同上面的那个Class-Class的例子:
上面两个的层次关系其实也是method的查找顺序。好像Module和Class有同等效力,那么我们来将两个组合起来。
class B def a p 'B a 1' end end module M def a p 'M a 1' super p 'M a END' end end class A < B include M def a p 'a 1' end def a p 'a 2' super p 'a 2 END' end end b = A.new b.a
输出结果:
那么我们可以看到这个的层次结构了:
也即是说,如果同时出现了Module和祖先Class,那么程序将先到Module中寻找。那么如果祖先Class也含有这个Module又会是怎么样的状况呢?
module M def a p 'M a 1' end end class B def a p 'B a 1' super p 'B a END' end include M end class A < B include M def a p 'a 1' end def a p 'a 2' super p 'a 2 END' end end b = A.new b.a
输出结果:
如果将Module混入它的祖先,那么这个层次结构又发生了变化:
也就是说如果“老子”和“小子”都想有“XXX”,那么这个“XXX”肯定是归“老子”的了,毕竟“小子”得懂得孝道,不光中国是这样,在日本也是这样的文化吧。
下面我们来讨论一下,这个调用super是否把参数也传进去了呢?
在《Ruby For Rails》中有这样一段描述:
我们仍然以一个例子来看看效果:
module M def a(x=5,y=6) p 'M a 1' p x p y end end class B def a(x=3,y=4) p 'B a 1' p x p y super(x) p 'B a END' end include M end class A < B include M def a p 'a 1' end def a(x=1,y=2) p 'a 2' p x p y super p 'a 2 END' super() end end b = A.new b.a(-1,-2)
输出结果:
果然,确实是有不同的效果。不过在使用super() 和super(a) 时,需要注意由于参数数据不全原方法需要是默认参数值的 。
最后,我给出一个综合的实例吧:
里面有很多错误和冗余,希望大家可以先自己看看输出结果然后再看实际结果,你们会有更多的收获的:
module M def report( a = 4, b =5) p "M report begin: a=#{a},b=#{b}" a = 6 super(a) p "M report end" end end class B def report(a=11,b=12) p "B report 1 begin: a=#{a},b=#{b}" p "B report 1 end" end def report(a=13,b=14) p "B report 2 begin: a=#{a},b=#{b}" #super p "B report 2 end" end end class C < B def report( a=8,b=9) p "C report 1 begin: a=#{a},b=#{b}" p "C report 1 end" end def report( a=7,b=3) p "C report 2 begin: a =#{a},b=#{b}" super() p "C report 2 End" end include M end class D < C def report( a = 2, b=1) p "D report 1 begin: a=#{a},b=#{b}" super(a,b) p "D report 1 end" end include M def report(a = -2, b=-1) p "D report 2 begin: a=#{a},b=#{b}" super p "D report 2 end" end end d = D.new d.report
输出结果:
通过实例,大家应该可以比较清晰的了解method查找调用规律和具体的super使用了。
现在做以下总结: