Groovy неявный вызов не работает для замыканий членов при использовании аннотации @CompileStatic

Этот код работает как положено (вывод 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}"
}

Итак, мой вопрос: почему я должен использовать явный вызов замыкания для замыканий членов при использовании статической компиляции? Это просто потому, что у Java нет неявного вызова? Если бы это было так, мы бы не стали явно ссылаться на callback закрытие передается в doStuff метод, а?

0 ответов

Другие вопросы по тегам