Callid
Callid

Reputation: 79

Groovy: What is the difference between accessing a field with "this" and without it?

In my current project, I have encountered a rather counter-intuitive difference between accessing a field with this and without this. Apparently, if I access my field without this, for some reason, I get a boolean instead of the field I'm trying to access:

//Weapon extends Simple extends Entity extends Matter extends Object


@groovy.transform.TypeChecked
abstract class Action {
    Matter tool

    boolean setTool(Matter t) {
        if (isValidTool(t)) {
            tool = t
            return true
        } else {
            return false
        }
    }

    boolean isValidTool(Matter m) {
        return true
    }
}

@groovy.transform.TypeChecked
class Attack extends Action {

    boolean isValidTool(Matter m) {
        return (m instanceof Entity)
    }

    boolean setTool(Matter t) {
        if (isValidTool(t)) {
            if (t instanceof Weapon) {
                tool = t
            } else {
                tool = new ImprovisedWeapon((Entity)t)
                //ImprovisedWeapon extends Weapon
            }
            return true
        } else {
            return false
        }
    }

    @Override
    Weapon getTool() {
        return (Weapon)this.tool
    }

    void test() {
        Weapon a = this.tool          //compile-time error
        Weapon b = (Weapon)this.tool  //works fine
        Weapon c = tool               //compile-time error
        Weapon d = (Weapon)tool       //compile-time error
    }
}

The errors I get, in order:

[Static type checking] - Cannot assign value of type project.matter.Matter to variable of type project.matter.simple.Weapon

[Static type checking] - Cannot assign value of type boolean to variable of type project.matter.simple.Weapon

[Static type checking] - Inconvertible types: cannot cast boolean to project.matter.simple.Weapon

The first error is explainable, I don't get to use getTool() after all, and instead effectively use this.@tool, which obviously returns a Matter. The other two errors, however, are very weird - no local variable tool is declared, the only tool around is the one inherited from Action, which is a Matter. The locally declared getTool() would even return a Weapon, and not a boolean. So, my question is, what exactly do I access here when I use tool, and why is it different from this.tool?

Upvotes: 1

Views: 102

Answers (1)

grdryn
grdryn

Reputation: 2017

Note: This might be better as a comment than an answer, but I don't have the reputation to comment.

I'm not sure why, but the error seems to have something to do with the return type of setTool. I think it might be more normal to have setters that don't return anything.

I've given this a try in a groovyConsole (groovy 2.2.1), and with your code (along with dummy classes for the missing ones), I experienced the last two errors that you see (not the first one). Once I set the return type of the setTool methods to void (and removed the return statements), those errors went away, but the first error then appeared for the third line (Weapon c = tool).

Unfortunately I can't explain why any of this is happening, but I hope it is of some help to you! Maybe someone else can give the reasoning behind the behaviour.

Upvotes: 1

Related Questions