Groovy探索之MOP 十二 方法的调用顺序
2009-05-22 07:57
246 查看
Groovy探索之MOP 十二 方法的调用顺序
我们知道,除了使用hook来拦截方法以外,我们还可以通过各种方式来实现方法。如,我们可以在类里直接实现方法;我们可以通过ExpandoMetaClass在运行期内添加方法;我们还可以通过ExpandoMetaClass在运行期内单独给一个对象添加方法。
所有的这些直接添加方法的途径,如果存在hook的话,都是要被hook拦截的。所以,我们可以说,系统是优先调用hook的。
而hook的调用顺序,我们在上一篇《Groovy探索之MOP 十一 运行期内覆盖invokeMethod》已经谈到过了。
本篇要谈到,却是除了hook方法以外的方法实现途径的调用顺序的问题。
我们都知道,如果有如下的一个类:
class Foo {
def getFoo()
{
'foo'
}
}
那么,我们可以通过如下的方法来调用它的方法:
def foo = new Foo()
println foo.foo
运行结果为:
foo
这就是我们的Gpath。
当然,我们也可以通过ExpandoMetaClass在运行期内添加这个"get"方法,如下:
Foo.metaClass.getFoo = {
->
'meta'
}
如果我们再做下面的测试:
def foo = new Foo()
println foo.foo
那么,运行结果为:
meta
从结果可以看出,在运行期内通过ExpandoMetaClass添加的方法是会覆盖类本身的方法的。
我们知道,在运行期内给类添加方法还有一种方式,即:
def mc = new ExpandoMetaClass(Foo.class,true)
mc.getFoo = {
->
'far'
}
mc.initialize()
下面,我将对上面的Foo类,在运行期内同时实行上面的两种方法的添加方式,然后在做测试,看看结果将会如何?
代码如下:
Foo.metaClass.getFoo = {
->
'meta'
}
def mc = new ExpandoMetaClass(Foo.class,true)
mc.getFoo = {
->
'far'
}
mc.initialize()
def foo = new Foo()
println foo.foo
}
运行结果为:
far
由此可见,后一种在运行期内添加方法的方式是会覆盖前一种在运行期内添加方法的方式的。
除此之外,我们还有一种在运行期内给对象添加方法的方式,如下:
def emc = new ExpandoMetaClass( foo.class, false )
emc.getFoo = {
->
"test" }
emc.initialize()
foo.metaClass = emc
最后,我们还将写代码来测试这最后一种方式与前几种方式的调用顺序。代码如下:
def mc = new ExpandoMetaClass(Foo.class,true)
mc.getFoo = {
->
'far'
}
mc.initialize()
def foo = new Foo()
def emc = new ExpandoMetaClass( foo.class, false )
emc.getFoo = {
->
"test" }
emc.initialize()
foo.metaClass = emc
println foo.foo
运行结果为:
test
可以看出,使用上面的方式在运行期内给一个对象添加的方法,会覆盖通过ExpandoMetaClass在运行期内给一个类添加的方法。
我们知道,除了使用hook来拦截方法以外,我们还可以通过各种方式来实现方法。如,我们可以在类里直接实现方法;我们可以通过ExpandoMetaClass在运行期内添加方法;我们还可以通过ExpandoMetaClass在运行期内单独给一个对象添加方法。
所有的这些直接添加方法的途径,如果存在hook的话,都是要被hook拦截的。所以,我们可以说,系统是优先调用hook的。
而hook的调用顺序,我们在上一篇《Groovy探索之MOP 十一 运行期内覆盖invokeMethod》已经谈到过了。
本篇要谈到,却是除了hook方法以外的方法实现途径的调用顺序的问题。
我们都知道,如果有如下的一个类:
class Foo {
def getFoo()
{
'foo'
}
}
那么,我们可以通过如下的方法来调用它的方法:
def foo = new Foo()
println foo.foo
运行结果为:
foo
这就是我们的Gpath。
当然,我们也可以通过ExpandoMetaClass在运行期内添加这个"get"方法,如下:
Foo.metaClass.getFoo = {
->
'meta'
}
如果我们再做下面的测试:
def foo = new Foo()
println foo.foo
那么,运行结果为:
meta
从结果可以看出,在运行期内通过ExpandoMetaClass添加的方法是会覆盖类本身的方法的。
我们知道,在运行期内给类添加方法还有一种方式,即:
def mc = new ExpandoMetaClass(Foo.class,true)
mc.getFoo = {
->
'far'
}
mc.initialize()
下面,我将对上面的Foo类,在运行期内同时实行上面的两种方法的添加方式,然后在做测试,看看结果将会如何?
代码如下:
Foo.metaClass.getFoo = {
->
'meta'
}
def mc = new ExpandoMetaClass(Foo.class,true)
mc.getFoo = {
->
'far'
}
mc.initialize()
def foo = new Foo()
println foo.foo
}
运行结果为:
far
由此可见,后一种在运行期内添加方法的方式是会覆盖前一种在运行期内添加方法的方式的。
除此之外,我们还有一种在运行期内给对象添加方法的方式,如下:
def emc = new ExpandoMetaClass( foo.class, false )
emc.getFoo = {
->
"test" }
emc.initialize()
foo.metaClass = emc
最后,我们还将写代码来测试这最后一种方式与前几种方式的调用顺序。代码如下:
def mc = new ExpandoMetaClass(Foo.class,true)
mc.getFoo = {
->
'far'
}
mc.initialize()
def foo = new Foo()
def emc = new ExpandoMetaClass( foo.class, false )
emc.getFoo = {
->
"test" }
emc.initialize()
foo.metaClass = emc
println foo.foo
运行结果为:
test
可以看出,使用上面的方式在运行期内给一个对象添加的方法,会覆盖通过ExpandoMetaClass在运行期内给一个类添加的方法。
相关文章推荐
- Groovy探索之MOP 八 运行期内给类和对象添加属性或方法
- Groovy探索之方法调用的动态性
- Groovy探索之MOP 六 运行期内添加构造器和静态方法
- Groovy探索之MOP 十五 方法名的动态性(1)
- Groovy探索之MOP 七 运行期内的方法和属性分析
- Groovy探索之MOP 十五 方法名的动态性(2)
- Groovy探索之MOP 一 invokeMethod和methodMissing方法
- android 7个生命周期方法分别在4个阶段按一定的顺序进行调用
- 亲测UISearchBar Delegate的11个方法和UISearchDisplay Delegate的12个方法的调用顺序
- view的执行过程,各种方法的调用先后顺序
- Groovy探索之MOP 四 使用ExpandoMetaClass来实现Mixin
- onTouch和onTouchEvent方法调用顺序
- 用WinDbg探索CLR世界 [4] 方法的调用机制
- 用WinDbg探索CLR世界 [4] 方法的调用机制之动态分析 - 下
- Silverlight 主页与页面用户组件中方法的调用顺序
- 关于heightForRow和cellForRow方法的调用次数和顺序的系统差异性
- UIViewController各方法的调用顺序
- 用WinDbg探索CLR世界 [4] 方法的调用机制
- 用WinDbg探索CLR世界 [4] 方法的调用机制之动态分析 - 上
- 继承中的方法调用顺序