when variable then def closure groovy scope

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:

  1. ¿Por qué no puedo acceder a una variable anotada con @Field inside method() ?
  2. ¿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:

  1. En su ejemplo, func() puede acceder al campo c porque ambos son miembros de la clase implícita. La clase Main no es, por lo que no puede.

  2. Debe pasar una referencia a la variable del script al method() . Una forma es pasar el objeto de binding 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() { } }