程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Groovy >> Groovy探索之MOP 十二 方法的調用順序

Groovy探索之MOP 十二 方法的調用順序

編輯:Groovy

我們知道,除了使用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在運行期內給一個類添加的方法。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved