Действительно ли возможно заменить отличный метод для существующего объекта?

Следующий код пытался заменить существующий метод в классе 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 org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod@103074e[name: abc params: [] returns: class java.lang.Object owner: class A]
Method public void A.abc()
new

Это означает, что, когда изменяют метакласс путем установки его на закрытие, он действительно не заменяет его, но просто добавляет другой метод, который это может назвать, таким образом приведя к метаклассу, имеющему два метода? Действительно ли возможно действительно заменить метод так вторая строка выходной "новой" печати?

При попытке понять это, я нашел, что DelegatingMetaClass мог бы помочь - который является большей частью Groovy способ сделать это?

20
задан Jean Barmash 15 March 2010 в 03:21
поделиться

1 ответ

Вы можете использовать метакласс для каждого экземпляра, чтобы изменить значение в существующем объекте, например итак:

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

Но, как вы видели, x будет иметь два связанных с ним метода (ну, на самом деле, метод и добавленное вами замыкание

Если вы измените определение A так, чтобы метод стал замыканием определение примерно так:

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

Тогда вы получите только одно закрытие в метаклассе и не получите никакого метода после изменения

14
ответ дан 30 November 2019 в 01:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: