2014-09-02 23 views
10

Questo codice:Utilizzo della funzione `Valuta`. Perché non funziona?

evaluate ("def test() { println \"Test is successful!\" }") 
test() 

risultati in eccezione:

FATAL: No firma del metodo: script1409644336796288198097.test() è applicabile per i tipi di argomento:() valori: [] Possibili soluzioni: usa ([Ljava.lang.Object;), getAt (java.lang.String), usa (java.util.List, groovy.lang.Closure), usa (java.lang.Class, groovy.lang.Closure), attendere(), attendere (lungo) groovy.lang.MissingMethodException: Nessuna firma del metodo: script1409644336796288198097.test() è applicabile per i tipi di argomenti:() valori: [] Possibili soluzioni: usare ([Ljava.lang.Object;), getAt (java.lang.String), usare (java.util.List, groovy.lang.Closure), usare (java.lang.Class, groovy.lang .Closure), attendere(), attendere (lungo) a org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap (ScriptBytecodeAdapter.java:55) ...

Quello che sto facendo di sbagliato?

+0

Non pensa di poter definire metodi/variabili in un Gstring e quindi chiamarli al di fuori dell'ambito di quel GString. Cosa stai cercando di fare? Probabilmente c'è un modo migliore di farlo. – jk47

+0

@ jk47, perché no? Ho bisogno di leggere una definizione del metodo dal file di testo ed eseguirla. – user626528

+0

Vuoi scrivere un programma che legge in qualsiasi funzione arbitraria e poi lo esegue? Perché? – jk47

risposta

9

Questa valutazione di script risulta nulla. È necessario restituire qualcosa o eseguire lo script e restituire il risultato.

Un esempio restituendo una chiusura invece di definire un metodo:

test = evaluate ('return { "Test is successful!" }') 
assert test() == "Test is successful!" 

E un esempio in cui lo script esegue il metodo in sé:

result = evaluate 'def test() { "eval test" }; return test()' 
assert result == "eval test" 

Se non è possibile modificare il codice di script, si può parse a class from the script, crea un nuovo oggetto, e quindi eseguire il metodo 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" 
+0

un modo per passare i parametri in callee usando uno dei primi 2 metodi? – user626528

+0

@ user626528 oops, scusa per il ritardo. Puoi passare i parametri usando ['binding'] (http://groovy.codehaus.org/Embedding+Groovy). – Will

+0

Grazie - molto utile. Trovato ho potuto cambiare leggermente per caricare i metodi da un file arbitrario non necessariamente nel classpath usando questa sintassi: loader.parseClass (new File ("- path to file--")) –

0

È possibile eseguire questa operazione utilizzando ExpandoMetaClass per aggiungere chiusure dinamiche alla propria classe. Dovresti analizzare prima la stringa per dividerla in nome della funzione, argomenti e codice.

methodName = "test" 
methodArgs = [] 
methodCode = """println "Hello World!" """ 

this.metaClass."$methodName"{ code, args -> 
    evaluate(code) 
} 

Poi si può chiamare facendo:

"$methodName"(code, arguments) 

o

test(code, arguments) 

per ottenere il risultato Hello World!

Si può leggere di più su ExpandoMetaClass qui http://groovy.codehaus.org/ExpandoMetaClass

0

Se una variabile ha un tipo non dichiarato, quindi it goes into the script binding. L'associazione è visibile a tutti i metodi, il che significa che i dati sono condivisi.

evaluate() is a helper method per consentire la valutazione dinamica delle espressioni groovy utilizzando gli script this vincolanti come ambito variabile.

In un collegamento variabile, è possibile declare a closure che non accetta argomenti e deve essere limitato alle chiamate senza argomenti.

Con tutto questo in mente, ecco il tuo script che funziona come previsto.

evaluate ("test = { -> println \"Test is successful!\" }") 
test() 
0

In aggiunta a tutte le altre risposte, se non si desidera modificare la struttura del codice è possibile utilizzare semplicemente return this alla fine del vostro groove-stringa:

lib = evaluate ("def test() { println \"Test is successful!\" }; return this") 
lib.test() 
Problemi correlati