2016-10-07 2 views
0

У меня возникли проблемы с пониманием работы кеша GroovyClassLoader с методами expando.Переопределить метод, уже добавленный через expandoMetaClass

В частности, я ожидал, что следующий код даст другой вывод для каждого вызова метода Number.test(), но это не тот случай.

int i = 1 

Number.metaClass.test = { 
    return "A string" 
} 
println i.test() 

println GroovySystem.metaClassRegistry.getMetaClass(Number.class) 
Number.metaClass = null 
println GroovySystem.metaClassRegistry.getMetaClass(Number.class) 

Number.metaClass.test = { 
    return "Another String" 
} 
println i.test() 

println GroovySystem.metaClassRegistry.getMetaClass(Number.class) 
GroovySystem.metaClassRegistry.removeMetaClass(Number.class) 
println GroovySystem.metaClassRegistry.getMetaClass(Number.class) 

Number.metaClass.test = { 
    return "Yet another String" 
} 
println i.test() 

Выход:

A string 
[email protected][class java.lang.Number] 
[email protected][class java.lang.Number] 
A string 
[email protected][class java.lang.Number] 
[email protected][class java.lang.Number] 
A string 

Edit:

Я попробовал еще несколько вещей. Похоже, моя система действует довольно странно. Учитывая следующий код:

def i = 1 

i.class 

Number.metaClass.test = { 
    return "A string" 
} 
println i.test() 

Number.metaClass = null 
Number.metaClass.test = { 
    return "Another String" 
} 
println i.test() 

GroovySystem.metaClassRegistry.removeMetaClass(Number.class) 
Number.metaClass.test = { 
    return "Yet another String" 
} 
println i.test() 

Когда я исполняю его в системе, он работает, как ожидалось (получение 3-х различных строк в выходной), но он выходит из строя (3 х A string), если я комментирую якобы бесполезно i.class.

Однако, если я исполню ее на groovy-console.appspot.com, это дает мне ожидаемый выход или без этой строки ...

Я вроде в убыток.

ответ

1

Когда вы создали int i = 9, он создал объект с текущим Number.metaClass. Он принимает создание нового метода (см. Number.metaClass.test = { "A string" }), но не допускает перегрузки уже существующих. Вы можете изменить метакласс объекта вместо:

int i = 1 

Number.metaClass.test = { "A string" } 
assert i.test() == "A string" 

Number.metaClass = null 

i.metaClass.test = { "Another String" } 
assert i.test() == "Another String" 

GroovySystem.metaClassRegistry.removeMetaClass(Number.class) 
assert i.test() == "Another String" 

i.metaClass.test = { "Yet another String" } 
assert i.test() == "Yet another String" 

Нуждаясь для вызова i.class выглядит как ошибка для меня ... Взглянув на JIRA я видел некоторые нерешенные и открыл ошибки. Я думал, что твоя были похожи на таких:

Переопределение методов классов Java метакласса не вступит в силу до тех пор экземпляр метакласса не изменяется: https://issues.apache.org/jira/browse/GROOVY-5065

Использование метакласса переопределения методов в иерархии классов не работает Ожидаемый результат: https://issues.apache.org/jira/browse/GROOVY-3942

методы Переопределение через .metaClass не ведет себя последовательно: https://issues.apache.org/jira/browse/GROOVY-6847

Удаление метода метакласса: https://issues.apache.org/jira/browse/GROOVY-4189


Первая часть моего ответа работает, если вы считаете, конкретный класс:

class Echo {} 
Echo.metaClass.test = { "A string" } 
def i = new Echo() 
assert i.test() == "A string" 

Echo.metaClass = null 
Echo.metaClass.test = { "Another String" } 
assert i.test() == "A string" 

i.metaClass.test = { "Another String" } 
assert i.test() == "Another String" 

i.metaClass.test = { "Yet another String" } 
assert i.test() == "Yet another String" 
+0

Спасибо за ваш ответ, он толкнул меня, чтобы исследовать некоторые больше, но, как вы можете увидеть в моем редактировать , Я не уверен, что объяснение так же просто, как и ваше. – sensei

+0

Еще раз спасибо. Я видел GROOVY-4189, который я пытался использовать, чтобы обойти проблему, но не объяснял ее. Я считаю, что это действительно очень сильно связано с GROOVY-6847, хотя, спасибо за это. Я поддержал ваш ответ, но я сохраняю этот вопрос нерешенным, поскольку поведение остается необъяснимым. Еще раз спасибо. – sensei

+0

Если ошибки не соответствуют вашему делу, рассмотрите возможность открытия билета JIRA – Will

Смежные вопросы