2010-03-15 93 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

相关问题