Использование функции `оценка`. Почему это не работает?
Этот код:
evaluate ("def test() { println \"Test is successful!\" }")
test()
приводит к исключению:
FATAL: Нет сигнатуры метода: script1409644336796288198097.test() применим для типов аргументов:() values: [] Возможные решения: use ([Ljava.lang.Object;), getAt (java.lang.String), используйте (java.util.List, groovy.lang.Closure), используйте (java.lang.Class, groovy.lang.Closure), wait(), wait (long) groovy.lang.MissingMethodException: Нет сигнатуры метода: script1409644336796288198097.test() применим для типов аргументов:() values: [] Возможные решения: use ([Ljava.lang.Object;), getAt (java.lang.String), используйте (java.util.List, groovy.lang.Closure), используйте (java.lang.Class, groovy.lang.Closure), wait(), wait (long) на org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:55)...
Что я делаю неправильно?
Ответы
Ответ 1
Результаты оценки script равны нулю. Вы должны либо что-то вернуть, либо выполнить script и вернуть результат.
Пример, возвращающий замыкание вместо определения метода:
test = evaluate ('return { "Test is successful!" }')
assert test() == "Test is successful!"
И пример, когда script выполняет сам метод:
result = evaluate 'def test() { "eval test" }; return test()'
assert result == "eval test"
Если вы не можете изменить код script, вы можете разобрать класс из script, создать новый объект, а затем выполните метод test()
:
def parent = getClass().getClassLoader()
def loader = new GroovyClassLoader(parent)
def clazz = loader.parseClass('def test() { "new class definition" }');
obj = clazz.newInstance()
assert obj.test() == "new class definition"
Ответ 2
Вы можете сделать это, используя ExpandoMetaClass, чтобы добавить динамические закрытия в свой собственный класс. Вам нужно будет сначала проанализировать строку, чтобы разбить ее на имя функции, аргументы и код.
methodName = "test"
methodArgs = []
methodCode = """println "Hello World!" """
this.metaClass."$methodName"{ code, args ->
evaluate(code)
}
Затем вы можете вызвать его, выполнив:
"$methodName"(code, arguments)
или
test(code, arguments)
Чтобы получить вывод Hello World!
Подробнее о ExpandoMetaClass вы можете узнать здесь http://groovy.codehaus.org/ExpandoMetaClass
Ответ 3
Если переменная имеет необъявленный тип, то она переходит в привязку script. Связывание видимо для всех методов, которые означают совместное использование данных.
evaluate()
является вспомогательным методом, позволяющим динамическую оценку выражений groovy с использованием связывания сценариев this
в качестве области переменных.
В привязке переменных вы можете объявить закрытие, которое не принимает аргументов и должно быть ограничено вызовами без аргументов.
С учетом всего этого, ваш script работает по назначению.
evaluate ("test = { -> println \"Test is successful!\" }")
test()
Ответ 4
В дополнение ко всем другим ответам, если вы не хотите изменять структуру своего кода, вы можете просто использовать return this
в конце groovy -string:
lib = evaluate ("def test() { println \"Test is successful!\" }; return this")
lib.test()