2010-03-15 38 views
16

下面的代碼試圖在Groovy類,以取代現有的方法:是否有可能取代現有對象的groovy方法?

class A { 
    void abc() { 
    println "original" 
    } 
} 

x= new A() 
x.abc() 
A.metaClass.abc={-> println "new" } 
x.abc() 
A.metaClass.methods.findAll{it.name=="abc"}.each { println "Method $it"} 

new A().abc() 

而且這將產生以下的輸出:

original 
original 
Method [email protected][name: abc params: [] returns: class java.lang.Object owner: class A] 
Method public void A.abc() 
new 

這是否意味着,當將其設置爲修改元類閉包,它並不真正代替它,但只是增加了另一種可以調用的方法,從而導致元類有兩種方法?是否有可能真正取代該方法,以便第二行輸出打印「新」?

當試圖找出它的時候,我發現DelegatingMetaClass可能會有幫助 - 是最Groovy的方式嗎?

回答

10

您可以使用每個實例的metaClass更改值在現有的對象,像這樣:

x= new A() 
x.abc() 
x.metaClass.abc={-> println "new" } 
x.abc() 
x.metaClass.methods.findAll{it.name=="abc"}.each { println "Method $it"} 

但是,正如你所看到的,X將與它(以及相關的兩個方法,實際上,方法和您添加

如果更改的定義關閉,使該方法成爲一個封閉的定義,像這樣:

class A { 
    def abc = { -> 
    println "original" 
    } 
} 

那麼你只會得到一個metaClass中的單關閉和更改後沒有方法

+2

謝謝 - 我想用它來覆蓋現有的Groovy類中的方法,所以我試圖避免修改原始類。 – 2010-03-15 14:46:09

1

我確定您的仍然有此問題;)但是...我在Fedora 17上運行Groovy版本1.8.7。我發現有你需要做的這個組合:

A.metaClass.abc = {-> println it} 
A obj = new A() 
obj.metaClass.abc = {-> println it} 
obj.abc 

從那裏出來,只要你想它會採取行動。當您要查找的方法,你還是會得到兩個:

Method [email protected][name: abc params: [] returns: class java.lang.Object owner: class A] 
Method public void A.abc() 

但至少你不必改變你的public void聲明。
不知道這是一個錯誤還是什麼。

5

我完全同意@tim_yates這個。但是,有一個辦法解決,如果你想避免修改原始類使用MethodClosure代替,如下圖所示:

class A { 
    void abc() { 
    println "original" 
    } 
} 

x = new A() 

//Create a Method Closure or Method pointer 
pointer = x.&abc 

//Replace Original call with Method pointer 
//x.abc() 
pointer() 

//Meta classed 
A.metaClass.abc={-> println "new" } 

//Call method pointer instead of original again 
//x.abc() 
pointer() 

A.metaClass.methods.findAll{it.name=="abc"}.each { println "Method $it"} 

new A().abc() 

你應該得到的期望是什麼:

original 
new 
Method [email protected] 
    [name: abc params: [] returns: class java.lang.Object owner: class A] 
Method public void A.abc() 
new 

基礎的在Groovy 2.2.1上。這個問題太老了。

+0

努力在這裏理解'MethodClosure'。使用這種方法有可能讓A的兩個實例(比如x和y)各自擁有自己的單獨方法'abc'? – HDave 2014-01-02 16:03:33

+0

不可以。一旦使用類A上的metaClass修改了'abc',則它適用於所有的A實例。MethodClosure只是可以在任何時間點調用的底層方法的Closure表示形式。 – dmahapatro 2014-01-02 17:43:02

+0

好 - 所以不可能有幾個'A類'的實例,每個實例都有一個不同的方法'abc'。遊民。 – HDave 2014-01-05 22:44:19

相關問題