Я считаю, что все это отличное и ничего особенного, чтобы согреться. Вот отличные концепции, которые вам нужно знать.
- Если последний аргумент метода является закрытием, вы можете поставить закрытие после закрывающей скобки для аргументов метода.
class MyClass {
void doStuff(String name, Closure c) {
c.call()
}
}
def o = new MyClass()
o.doStuff('x') {
println "hello"
}
- Вы можете реализовать метод, отсутствующий на вашем объекте. Если кто-то пытается вызвать метод, который не существует, вы можете сделать что-то
class MyClass {
def methodMissing(String name, args) {
println "You invoked ${name}(${args})"
}
}
def o = new MyClass() {
o.thisMethodDoesNotExist('foo')
}
- Вы можете установить делегата на закрытие
class MyBean {
void include(String pattern) {...}
void exclude(String pattern) {...}
}
class MyClass {
private MyBean myBean = new MyBean()
void doStuff(Closure c) {
c.setDelegate(myBean)
c.call()
}
}
def o = new MyClass()
o.doStuff {
include 'foo'
exclude 'bar'
}
Эти 3 отличные функции в значительной степени объясняют "магическое" поведение, происходящее в скрипте gradle, когда Java-разработчики ломают голову.
Итак, давайте разберем ваш фрагмент
task myTask(type:Foo) {
doLast {...}
}
Давайте добавим несколько скобок, а также добавим неявные ссылки на проекты. Давайте также извлечем замыкание в переменную
Closure c = {
doLast {...}
}
project.task(project.myTask([type: Foo.class], c))
Метод project.myTask(...)
не существует, и поведение в конечном итоге реализуется с помощью функциональности methodMissing
. Gradle установит делегата на закрытие экземпляра задачи. Таким образом, любые методы в замыкании будут делегированы вновь созданной задаче.
В конечном счете, вот что логически называется
Action<? extends Task> action = { task ->
task.doLast {...}
}
project.tasks.create('myTask', Foo.class, action)
См. TaskContainer.create (Строка, Класс, Действие)