6

Is there a way to access global variable, declared in the script, from the static method of the class, declared in the same script?

For example

def s = "12345"

class MyClass {
    static def method() {
        println s
    }
}

Because that way it fails with the error

You attempted to reference a variable in the binding or an instance variable from a static context

which is expected though.

lapots
  • 12,553
  • 32
  • 121
  • 242

3 Answers3

10

There is a related discussion at this question:

Groovy scope - how to access script variable in a method

Related in that both questions refer to using a global variable within a class, but this question differs somewhat in that you are seeking to use a static method which alters how you pass the script instance or binding (2 choices).

Passing the Script's Instance

import groovy.transform.Field

@Field def s = "12345"

class MyClass {
    static def method(si) {      
      return si.s
    }
}

assert MyClass.method(this) == "12345"

Passing the Script's binding

s = "12345" // NOTE: no 'def'

class MyClass {
    static def method(b) {      
      return b.s
    }
}

assert MyClass.method(binding) == "12345"
Community
  • 1
  • 1
tylerwal
  • 1,858
  • 2
  • 15
  • 20
  • 2
    so basically as with the basic `java` approach? I thought that Groovy allows it to do somehow as it more flexible. – lapots Feb 16 '16 at 07:14
6

Well, the problem is that in Groovy there is no such thing as a global variable. What is loosely considered a global variable is actually a static property within some class.

For example, if you remove the println line so that the code compiles, you get something like this out of the compiler:

public class script1455567284805 extends groovy.lang.Script { 

    ...

    public java.lang.Object run() {
        return java.lang.Object s = '12345'
    }

    ...

}

public class MyClass implements groovy.lang.GroovyObject extends java.lang.Object { 

    ...

    public static java.lang.Object method() {
        // This is where the println would have been.
        return null
    }

    ...
}

As you can see, an additional class is created and the the s variable is declared within the method run() of that class. This makes the variable inaccessible to your other class.

Note: Removing the def will not address this issue.

Solution

Your best bet is to place your "global variables" into a class, possibly as static properties, like this:

class Global {
    static Object S = "12345"
}

class MyClass {
    static def method() {
        println Global.S
    }
}
Emmanuel Rosa
  • 9,697
  • 2
  • 14
  • 20
  • oh! I completely forgot that `def` creates variables inside `run` method of the script. I should have declared variable without `def`. I think It might be possible to do with some custom AST transformation – lapots Feb 16 '16 at 06:53
1

You included a variable type with the s variable (by using the def type). In a Groovy script, this is treated as a local variable - and local to the run() method that is generated - which is kind of like a main() class. As a result, the variable is not available in other methods or classes.

If you remove the def you will be able to make use of the s variable.

Here is the Groovy documentation that explains this further.

mnd
  • 2,709
  • 3
  • 27
  • 48