5

Couldn't really figure out/find what a difference between thouse two

import groovy.lang.Binding;
import groovy.lang.GroovyShell;

class Scratch {
    public static void main(String[] args) {
        Binding binding = new Binding();
        Integer p = 1,
                v = 1;
        binding.setProperty("p", p);
        binding.setVariable("v", v);

        GroovyShell shell = new GroovyShell(binding);
        shell.evaluate("p++;v++;");
        System.out.println(String.format("BINDING Property = %s, Variable = %s", binding.getProperty("p"), binding.getVariable("v")));
        System.out.println(String.format("JAVA Property = %s, Variable = %s", p, v));
    }
}

Output is:

BINDING Property = 2, Variable = 2
JAVA Property = 1, Variable = 1

Is there is some purpose for using one or another.

Ivan Baranuk
  • 156
  • 1
  • 12

1 Answers1

3

The class groovy.lang.Binding overloads setProperty and getProperty methods so you can access variables using field accessor or subscript operator. If you take a look at the source code of these two methods you will find something like this:

/**
 * Overloaded to make variables appear as bean properties or via the subscript operator
 */
public Object getProperty(String property) {
    /** @todo we should check if we have the property with the metaClass instead of try/catch  */
    try {
        return super.getProperty(property);
    }
    catch (MissingPropertyException e) {
        return getVariable(property);
    }
}

/**
 * Overloaded to make variables appear as bean properties or via the subscript operator
 */
public void setProperty(String property, Object newValue) {
    /** @todo we should check if we have the property with the metaClass instead of try/catch  */
    try {
        super.setProperty(property, newValue);
    }
    catch (MissingPropertyException e) {
        setVariable(property, newValue);
    }
}

It means that in Groovy you could express

binding.setVariable("v", v);

as

binding.v = v
// or
binding['v'] = v

Of course if the property you are accessing with setProperty or getProperty exists in the class, then you won't be able to set a variable using this name and in this case, you need to call binding.setVariable() directly.

On the other hand, methods getVariable and setVariable reads or puts values directly to the internal map. Here is what its source code looks like:

/**
 * @param name the name of the variable to lookup
 * @return the variable value
 */
public Object getVariable(String name) {
    if (variables == null)
        throw new MissingPropertyException(name, this.getClass());

    Object result = variables.get(name);

    if (result == null && !variables.containsKey(name)) {
        throw new MissingPropertyException(name, this.getClass());
    }

    return result;
}

/**
 * Sets the value of the given variable
 *
 * @param name  the name of the variable to set
 * @param value the new value for the given variable
 */
public void setVariable(String name, Object value) {
    if (variables == null)
        variables = new LinkedHashMap();
    variables.put(name, value);
}
Szymon Stepniak
  • 32,284
  • 9
  • 78
  • 108
  • 1
    `The class groovy.lang.Binding overloads setProperty and getProperty methods` That was confusing part. Somehow I dint't check source code before questioning. – Ivan Baranuk Dec 03 '18 at 13:37