使用@CompileStatic注释时,Groovy隐式调用不适用于成员闭包

时间:2014-01-15 21:52:54

标签: groovy closures

此代码按预期工作(输出为j.doe):

class Sample {

    Closure formatFirstName
    Closure formatLastName

    void doStuff (String fname, String lname, Closure callback) {
        formatFirstName(fname) { String fnameError, String formattedFname ->
            formatLastName(lname) { String lnameError, String formattedLname ->
                String errors = "${fnameError ? "${fnameError}, " : ''}${lnameError ?: ''}"
                callback(errors, formattedFname, formattedLname)
            }
        }    
    }

}

Closure ffn = { String fname, Closure callback ->
    String firstInitial = fname?.substring(0,1)

    if (!firstInitial)
        callback('invalid first name', null)
    else
        callback(null, firstInitial.toLowerCase())
}

Closure fln = { String lname, Closure callback ->
    String lastPrefix = lname?.size() > 2 ? lname.substring(0,3) : null

    if (!lastPrefix)
        callback('invalid last name', null)
    else
        callback(null, lastPrefix.toLowerCase())
}

Sample sample = new Sample(formatFirstName: ffn, formatLastName: fln)

sample.doStuff('John', 'Doe') { String errors, String formattedFname, String formattedLname ->
    if (errors)
        println errors
    else 
        println "${formattedFname}.${formattedLname}"
}

添加@CompileStatic注释会导致异常:

groovy.lang.MissingMethodException: No signature of method: Sample$_doStuff_closure1.doCall() is applicable for argument types: (java.lang.String, Sample$_doStuff_closure1_closure2) values: [Doe, Sample$_doStuff_closure1_closure2@bb70963]
Possible solutions: doCall(java.lang.String, java.lang.String), findAll(), findAll()
    at Sample$_doStuff_closure1.doCall(ConsoleScript226:11)
    at ConsoleScript226$_run_closure1.doCall(ConsoleScript226:26)
    at Sample.doStuff(ConsoleScript226:10)
    at Sample$doStuff.call(Unknown Source)
    at ConsoleScript226.run(ConsoleScript226:40)

(带@CompileStatic注释的代码)

import groovy.transform.CompileStatic

@CompileStatic
class Sample {

    Closure formatFirstName
    Closure formatLastName

    void doStuff (String fname, String lname, Closure callback) {
        formatFirstName(fname) { String fnameError, String formattedFname ->
            formatLastName(lname) { String lnameError, String formattedLname ->
                String errors = "${fnameError ? "${fnameError}, " : ''}${lnameError ?: ''}"
                callback(errors, formattedFname, formattedLname)
            }
        }    
    }

}

Closure ffn = { String fname, Closure callback ->
    String firstInitial = fname?.substring(0,1)

    if (!firstInitial)
        callback('invalid first name', null)
    else
        callback(null, firstInitial.toLowerCase())
}

Closure fln = { String lname, Closure callback ->
    String lastPrefix = lname?.size() > 2 ? lname.substring(0,3) : null

    if (!lastPrefix)
        callback('invalid last name', null)
    else
        callback(null, lastPrefix.toLowerCase())
}

Sample sample = new Sample(formatFirstName: ffn, formatLastName: fln)

sample.doStuff('John', 'Doe') { String errors, String formattedFname, String formattedLname ->
    if (errors)
        println errors
    else 
        println "${formattedFname}.${formattedLname}"
}

使用显式调用(即closure.call)现在可以再次使用:

import groovy.transform.CompileStatic

@CompileStatic
class Sample {

    Closure formatFirstName
    Closure formatLastName

    void doStuff (String fname, String lname, Closure callback) {
        formatFirstName.call(fname) { String fnameError, String formattedFname ->
            formatLastName.call(lname) { String lnameError, String formattedLname ->
                String errors = "${fnameError ? "${fnameError}, " : ''}${lnameError ?: ''}"
                callback(errors, formattedFname, formattedLname)
            }
        }    
    }

}

Closure ffn = { String fname, Closure callback ->
    String firstInitial = fname?.substring(0,1)

    if (!firstInitial)
        callback('invalid first name', null)
    else
        callback(null, firstInitial.toLowerCase())
}

Closure fln = { String lname, Closure callback ->
    String lastPrefix = lname?.size() > 2 ? lname.substring(0,3) : null

    if (!lastPrefix)
        callback('invalid last name', null)
    else
        callback(null, lastPrefix.toLowerCase())
}

Sample sample = new Sample(formatFirstName: ffn, formatLastName: fln)

sample.doStuff('John', 'Doe') { String errors, String formattedFname, String formattedLname ->
    if (errors)
        println errors
    else 
        println "${formattedFname}.${formattedLname}"
}

所以我的问题是:为什么在使用compile static时我必须对成员闭包使用显式闭包调用?是因为Java没有隐式调用吗?如果是这种情况,我们不必显式调用传递给callback方法的doStuff闭包吗?

0 个答案:

没有答案