Если вы не хотите использовать скобки, вам нужно разделить аргументы замыкания на ,
, чтобы сообщить компилятору, что вы хотите выполнить label
со следующими двумя параметрами:
Groovy имеет этот синтаксический сахар, который позволяет вам передавать замыкание вне скобок, когда замыкание является последним параметром прототипа функции, поэтому работают следующие обозначения:
Но это все равно эквивалент упомянутых ранее.
Как сделать label "lbl" { }
действительным утверждением?
Если вы действительно хотите скомпилировать код, например:
label "lbl" {
println "call $it"
}
вам нужно знать одну вещь - такие обозначения эквивалентны:
label("lbl" {
println "call $it"
})
Это означает, что есть функция label
, которая принимает один параметр - значение, возвращаемое функцией lbl
, которая принимает один параметр - closure. Реализация этих функций может выглядеть следующим образом:
def label = { value ->
// do something with value
println "The value accepted by label function is '${value}'"
}
def lbl = { callback ->
callback?.call()
}
label "lbl" {
println "call $it"
}
Компилируется и печатает следующий вывод в консоль:
call null
The value accepted by label function is 'null'
Конечно, как вы можете видеть, вы должны реализовать метод lbl
, и в большинстве случаев это очень ограничивает - вы не можете вызвать функцию label
с любым параметром, отличным от lbl
. Вы могли бы реализовать функцию methodMissing(name, args)
Groovy, которая вызывается всякий раз, когда вызывается несуществующий метод. Рассмотрим следующий пример:
def methodMissing(String name, args) {
if (args.length == 1 && args[0] instanceof Closure) {
println "Running missing method '${name}'"
return args[0].call()
}
throw new MissingMethodException(name, this.class, args)
}
def label = { value ->
// do something with value
println "The value accepted by label function is '${value}'"
}
def lbl = { callback ->
callback?.call()
}
label "lbl" {
println "call $it"
}
label "test" {
println "nothing"
}
В этом случае, когда вызывается label "test" { println "nothing" }
, Groovy использует missingMethod
, поскольку метод test
не существует в контексте времени выполнения.
call null
The value accepted by label function is 'null'
Running missing method 'test'
nothing
The value accepted by label function is 'null'
Однако это не значит, что вы можете думать об этом как об эквивалентном избавлении от разделителя комы или скобок из вашего кода . Это пример простого DSL, написанного на Groovy, который использует механизм methodMissing
для удовлетворения вызова несуществующих методов. Этот последний пример фактически такой же, как:
label("test" {
println "nothing"
})
Функция, которая ожидает один аргумент, и в этом случае мы предоставляем его в результате test
вызова метода с одним параметром { println "nothing" }
.
Я бы настоятельно рекомендовал принять тот факт, что Groovy требует от вас разделять аргументы функции с помощью комы и не использовать такие DSL для удаления комы или скобок из кода. Groovy DSL очень мощный, и вы должны знать, что вы делаете, когда решите использовать этот инструмент в своем коде. Например, подумайте, что произойдет, если вы позвоните:
label "test" { println "something" }
и по какой-то причине метод, определенный как следующее закрытие:
def test = { int num -> num + 2 }
существует в вашем классе. Вы начнете получать исключения, потому что methodMissing
больше не вызывается в этом случае. Метод test
существует, но у него нет подписи, которая принимает одно замыкание.