variable - groovy when then
Ámbito de Groovy: cómo acceder a la variable de script en un método (2)
Tengo una pregunta sobre reglas de alcance en Groovy. En el siguiente fragmento, tengo tres variables, a
tiene alcance local, b
tiene un alcance de script, c
debe tener el alcance de script usando la anotación @Field
.
#!/usr/bin/groovy
import groovy.transform.Field;
//println org.codehaus.groovy.runtime.InvokerHelper.getVersion()
def a = 42;
b = "Tea"
@Field def c = "Cheese"
void func()
{
// println a // MissingPropertyException
println b // prints "Tea"
println c // prints "Cheese" with groovy 2.1.2, MissingPropertyException with groovy 1.8.6
}
class Main
{
def method()
{
// println a // MissingPropertyException
// println b // MissingPropertyException
// println c // MissingPropertyException with both 1.8.6. and 2.1.2
}
}
func();
new Main().method();
Obtengo MissingPropertyException
en las líneas indicadas con comentarios. Se esperan las excepciones en a
, ya que esa variable tiene alcance local. Pero esperaría que b
fuera accesible dentro del method()
- no lo es. @Field
no hace nada en Groovy 1.8.6, aunque después de la actualización funciona, así que supongo que es un error antiguo. Sin embargo, c
es inaccesible dentro del method()
con cualquier versión.
Entonces mis preguntas son:
- ¿Por qué no puedo acceder a una variable anotada con
@Field
insidemethod()
? - ¿Cómo puedo hacer referencia a una variable de script dentro de
method()
?
Cuando tiene métodos o declaraciones fuera de una declaración de class
en un script groovy, se crea una clase implícita. Para responder tu pregunta:
En su ejemplo,
func()
puede acceder al campoc
porque ambos son miembros de la clase implícita. La claseMain
no es, por lo que no puede.Debe pasar una referencia a la variable del script al
method()
. Una forma es pasar el objeto debinding
definido implícitamente, a través del cual puede acceder a todas las variables de ámbito de script.
Ejemplo:
#!/usr/bin/groovy
import groovy.transform.Field;
//println org.codehaus.groovy.runtime.InvokerHelper.getVersion()
def a = 42;
b = "Tea"
@Field def c = "Cheese"
void func()
{
// println a // MissingPropertyException
println b // prints "Tea"
println c // prints "Cheese" with groovy 2.1.2, MissingPropertyException with groovy 1.8.6
}
class Main
{
def scriptObject
def binding
def method()
{
// println a // MissingPropertyException
println binding.b
println scriptObject.c
}
}
func();
new Main(scriptObject: this, binding: binding).method();
Este script y Main
se generan como dos clases separadas dentro del mismo archivo.
Como Main
no es una clase interna de la clase Script, no puede ver el campo java.lang.Object c
dentro de la clase de script.
Tendría que envolver explícitamente este script en una clase con un método static main( args )
(y una clase Main
interna) o tendría que pasar una instancia de la clase de script al método como: Main.method( this )
Este es el tipo de cosa que genera el script anterior:
class Script032034034 {
Object c
Script032034034() {
c = ''Cheese''
}
Object run() {
Object a = 42
b = ''Tea''
func()
new Main().method()
}
void func() {
println b
println c
}
}
class Main {
Object method() {
}
}