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

Groovy探索之MOP 十一 運行期內覆蓋invokeMethod

編輯:Groovy

我們很早就會使用Groovy語言的hook,即"invokeMethod"方法和其他的幾個方法。我們會在一個類中實現"invokeMethod"方法,用來分派所有的或部分的在運行期內調用的該類實例的方法。這些我們在《Groovy探索之MOP 一 invokeMethod和methodMissing方法》已經詳細的談到過。

現在,我們已經深入的接觸到了Groovy語言的MetaClass,更是也到處使用到了ExpandoMetaClass。我們都已經知道,ExpandoMetaClass的靈活性,不是hook能夠比擬的。我們就想,既然使用ExpandoMetaClass能夠在運行期內給一個類增加方法,那麼,我們是否也可以在運行期內增加hook方法呢?

我們可以回答,是。還是先來看一個簡單的例子吧!

我們還是有這麼一個簡單的類:

class Foo
{
def foo()
{
'foo'
}
}

我們現在嘗試著在運行期內增加"invokeMethod"方法:

Foo.metaClass.invokeMethod = {
String name,args1 ->
'test'

}

接著,我們來測試這個運行期內增加的"invokeMethod"方法:

def foo = new Foo()
println foo.foo()
println foo.test()

運行結果為:

test
test

可以看出,我們在運行期內增加的"invokeMethod"方法攔截了Foo類的實例的所有的方法。

當然,如果我們想把"invokeMethod"方法攔截的方法中,已經存在於Foo類的方法,如"foo",交給Foo類本身的方法來處理。那麼,我們就可以如下實現"invokeMethod"方法:

Foo.metaClass.invokeMethod = {
String name,args1 ->
def m = Foo.metaClass.getMetaMethod(name,args1)
def result
if(m)
result = m.invoke(delegate,args1)
else
result = 'test'
result
}

我們再運行上面的測試代碼,就會得到如下的結果:

foo
test

現在,我們來定義幾個名詞,我們把類本身實現的"invokeMethod"方法稱為對象的"invokeMethod"方法,而把在運行期內通過ExpandoMetaClass增加的"invokeMethod"方法稱為metaClass的"invokeMethod"方法。

現在的問題是,如果一個對象,同時實行了對象的"invokeMethod"方法和metaClass的"invokeMethod"方法,那麼該調用誰?

你肯定會說,這個問題很簡單啊,我們來做一個簡單的測試不就知道了。好,現在,我們先來看看這個簡單的測試。

首先,我們把上面的Foo類增加"invokeMethod"方法:

class Foo
{
def foo()
{
'foo'
}

def invokeMethod(String name,args)
{
'invoke'
}
}

同時,我們在運行期內也增加該方法,然後做測試:

Foo.metaClass.invokeMethod = {
String name,args1 ->
def m = Foo.metaClass.getMetaMethod(name,args1)
def result
if(m)
result = m.invoke(delegate,args1)
else
result = 'test'
result
}
def foo = new Foo()
println foo.foo()
println foo.test()

運行的結果為:

foo
test

從結果可以看出,metaClass的"invokeMethod"方法覆蓋了對象的"invokeMethod"方法。即如果存在metaClass的"invokeMethod"方法,則優先調用metaClass的"invokeMethod"方法,而不管對象的"invokeMethod"方法是否存在。

最後,我們還定義一個名詞:GroovyInterceptable的"invokeMethod"方法。這個名詞其實我們在《Groovy探索之MOP 一 invokeMethod和methodMissing方法》也接觸過,就是一個類如果實現了"GroovyInterceptable"接口,那麼它的類本身的"invokeMethod"方法,就是GroovyInterceptable的"invokeMethod"方法。如下所示:

class Foo implements GroovyInterceptable{
def foo()
{
'foo'
}

def invokeMethod(String name,args)
{
'invoke'
}
}

現在,我們需要知道,如果一個對象的GroovyInterceptable的"invokeMethod"方法和metaClass的"invokeMethod"方法都存在,那麼又是如何調用的?

還是對上面已經實現了"GroovyInterceptable"接口的Foo類如下測試:

Foo.metaClass.invokeMethod = {
String name,args1 ->
def m = Foo.metaClass.getMetaMethod(name,args1)
def result
if(m)
result = m.invoke(delegate,args1)
else
result = 'test'
result
}
def foo = new Foo()
println foo.foo()
println foo.test()

運行結果為:

invoke
invoke

從運行結果可以看出,GroovyInterceptable的"invokeMethod"方法是優先於metaClass的"invokeMethod"方法的調用的;或者說,如果一個對象同時存在GroovyInterceptable的"invokeMethod"方法和metaClass的"invokeMethod"方法,那麼系統將調用GroovyInterceptable的"invokeMethod"方法,而不管metaClass的"invokeMethod"方法。

最後,我們來做一個總結吧。對於一個對象的方法調用,如果該對象的類實現了"GroovyInterceptable"接口,那麼,系統將調用GroovyInterceptable的"invokeMethod"方法;否則,系統將調用metaClass的"invokeMethod"方法;如果該對象沒有實現metaClass的"invokeMethod"方法,那麼系統將調用對象的"invokeMethod"方法。

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