Groovy 'No signature of method' running Cl

2019-09-07 06:48发布

问题:

I have a closure that's executed against another Groovy object as the delegate. I can do:

foo {
    bar {
        major = 1
    }
}

but when I do:

foo {
    bar {
        major 1
    }
}

I get an error:

> No signature of method: my.Bar.major() is applicable for argument types (java.lang.Integer) values: [1]
Possible solutions: setMajor(java.lang.Integer), getMajor(), wait(), any(), setMajor(java.lang.String), wait(long)

Bar looks something like:

class Bar {
    Integer major
    Integer getMajor() { return this.major }
    def setMajor(Integer val) { this.major = val }
}

I thought Groovy made getters/setters transparent when dealing with property references and that referring to bar.major was the same as bar.get/setMajor(). Am I understanding this wrong, or does the meta class lookup route differ when you throw Closure delegates into the mix? The resolution strategy is DELEGATE_FIRST.

For more context: http://forums.gradle.org/gradle/topics/groovy-no-signature-of-method-running-closure-against-delegate

回答1:

you would have to add also void major(Integer val). major = 1 is groovy-short for setMajor(1) while major 1 is short for major(1). (see Section Optional parenthesis)

Optional parenthesis

Method calls in Groovy can omit the parenthesis if there is at least one parameter and there is no ambiguity.

println "Hello world"
System.out.println "Nice cheese Gromit!"

E.g.:

class X {
    Integer major
    void major(Integer m) { major = m }
}

def x = new X()
x.major = 1 // x.setMajor(1)
assert x.major==1 // x.getMajor()==1
x.major 2 // x.major(2)
assert x.major==2

If you need this behaviour alot, you can add a methodMissing for this case. E.g.:

class X {
    Integer major
    def methodMissing(String name, args) {
        if (this.hasProperty(name) && args.size()==1) {
            this."$name" = args[0]
        } else {
            throw new MissingMethodException(name, this.class, args)
        }
    }
}

def x = new X()
x.major = 1
assert x.major==1
x.major 2
assert x.major==2


标签: groovy gradle