Hi, I've been caught out by this in the past as well. It's actually quite simple...
A Groovy Script like: String test void func(){ println(test) } test = 'hello' func() Gets compiled to a class as: class MyScript extends Script { def run() { String test test = 'hello' func() } void func() { println(test) } } All "lose code" gets collected into the run() method, and functions defined in your script are copied into the class as methods. As you can see, the declaration "String test" ends up as part of the run() method, and therefore the "test" variable is scoped locally to that run() method. It's not a class member. Your func() method is not able to see it. You can work around that by annotating the "String test" declaration with the @Field annotation: @Field String test void func() { println(test) } test = 'hello' func() This will cause the "String test" declaration to be included in the Script class as a class member: class MyScript extends Script { String test def run() { test = 'hello' func() } void func(){ println(test) } } This is described in https://docs.groovy-lang.org/latest/html/documentation/core-metaprogramming.html#xform-Field. It is also very lightly mentioned in https://groovy-lang.org/structure.html#_variables, but that page probably doesn't make it clear enough. Maarten On 14/10/2020 15:45, Anton Shepelev wrote:
Hello, all I tried to define a global variable in a Groovy script. Section 1.1. of the "Semantics" documents says that one way to define a variable is via its type, so I defined one in the global scope of my script: String test void func() { println(test) } test = 'hello' func() but it failed with the error: "No such property: test for class: Script1". That didn't explain to me what the problem was, but I learned that the script was looking for a property named `test' in the global autogenerated Script class. OK, thought I, I will give it what it asks, and cosulted section 1.6.2. (Properties) of the "Object orientation" document, which told me that the definition of a property is identical to the definition of a variable I used above, i.e. that String test defienes a string property `test' or a string variable `test', depending on context. I was now stuck and resorted to an internet search, which brought up the following page Groovy Variable Scope: https://www.baeldung.com/groovy/variable-scope where I read: Scopes in Groovy follow, above all, the rule that all variables are created public by default. This means that, unless specified, we'll be able to access any variable we created from any other scope in the code. Why, then, is `test' inaccessible from the function in my script? And below: The easiest way to create a global variable in a Groovy script is to assign it anywhere in the script without any special keywords. We don't even need to define the type: x = 200 After I removed the "String test" line from my script it started to work, but why? I returned to the "Semantics" document and read section 1.2. (Variable assignment) to see whether the assignment operator may have the side effect of defining a missing variable, but there is no indication that it has. Can you please explain to me, preferable with the correspoding references to official documentation, why my scirpt does not work whereas the modified one does?