此代码按预期工作(输出为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
闭包吗?