程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Groovy >> Groovy探索之MOP 五 針對接口類型的動態性

Groovy探索之MOP 五 針對接口類型的動態性

編輯:Groovy

這裡所說的接口類型,在Java語言和Groovy語言中,當然是既包括了基類類型和接口。所謂"接口類型的動態性",指的是在運行期內給基類或接口動態的添加方法,使得基類以及它的子類、接口的實現,都能訪問這些方法。

這個功能一向是我比較感興趣的一個功能。因為我們在編程的實踐中,會使用各種各樣的應用API,還有JDK,在使用它們的過程中,可能有一些接口及它們的子類我們會經常使用到,但是在使用的過程中,我們又感到非常的不方便。這時候,我們可以使用Categories機制來對我們所使用的類進行擴充功能,但如果一個類有很幾個子類或者一個接口有好幾個實現,對於所有的子類或實現,我們都希望進行相同的功能擴充。那麼,如果我們使用Categories機制的話,我們就不得不對所有的子類或實現進行依次擴充。這就造成了重復性的勞動。

而我們使用ExpandoMetaClass機制的話,則只需要對基類或者接口進行功能擴充,那麼所有的子類或實現都能夠得到該功能。這是多麼的激動人心啊!

首先,我們來看一個基類和它的子類的例子。

我們已經擁有了如下的一個基類:

class A
{
def afuction()
{
println 'a'
}
}

同時,我們也已經有了好幾個它的子類,下面就是一個例子:

class B extends A
{
def bfuction()
{
println 'b'
}
}

現在,我們希望給A類在運行期內增加一個方法,同時,B類也擁有了該方法。

首先,使得ExpandoMetaClass enabled globally:

ExpandoMetaClass.enableGlobally()

接著,我們給A類增加方法:

A.metaClass."aAndb" = {
->
println 'a and b'
}

下面,我們就可以測試了:

def a = new A()

a.aAndb()

def b = new B()

b.aAndb()

運行結果為:

a and b
a and b

果然達到了我們的要求。一切都很簡單,但需要注意的是在給基類添加方法之前,一定要加上"ExpandoMetaClass.enableGlobally()",否則,就會報告如下的錯誤:

Exception in thread "main" groovy.lang.MissingMethodException: No signature of method: mop.B.aAndb() is applicable for argument types: () values: {}
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:54)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:59)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodN(ScriptBytecodeAdapter.java:169)
at mop.A.invokeMethod(Testor3.groovy)

同樣,我們也可以對一個接口的所有的實現進行功能擴展。比如,我們想對List接口進行功能擴展,舉一個簡單的例子--我們想獲取一個List對象的倒序List對象,就可以進行如下的編程:

ExpandoMetaClass.enableGlobally()

List.metaClass.reversed = {
->
def rl = []
for(int i in (delegate.size()-1..0))
{
rl << delegate.getAt(i)
}
rl
}

跟基類的原理一樣,我們是在接口上添加功能。下面我們就可以進行測試了:

def list = [1,2,3]

list = list.reversed()

println list

 

運行的結果為:

[3, 2, 1]

一切也都顯得比較簡單,唯一需要注意的是,記得加上如下的語句:

ExpandoMetaClass.enableGlobally()

否則,同樣會報"MissingMethodException"的錯誤。

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