关于Groovy无def参数及task调用与taskDefinition数组化的疑问
Groovy未声明def的方法参数与task调用逻辑解析
一、未用def声明的方法参数规则
在Groovy里,方法参数如果既不指定具体类型,也不用def关键字声明,会被默认当作**Object类型的可变参数(varargs)**处理。意思是你传入的所有参数会被自动打包成一个Object[]数组,赋值给这个参数变量。比如:
def test(args) { println args.class.name // 输出 [Ljava.lang.Object; println args[0] // 取第一个传入的参数 } test("hello", 123)
上面的args就是包含"hello"和123的数组,能通过下标访问单个元素。
二、task woo { ... }的调用逻辑拆解
先看核心调用代码:
task woo { say "hello" // From task and "world" // From project }
1. Groovy的语法糖:括号省略与闭包后置
Groovy有两个关键语法糖让这段代码成立:
- 方法调用的括号可以省略,比如
task("woo")可以写成task "woo"; - 如果方法的最后一个参数是闭包,可以把闭包移到方法括号外面,比如
task("woo", { ... })可以写成task "woo" { ... },进一步省略括号就变成了task woo { ... }。
所以这段代码等价于标准写法:
task("woo", { say "hello" and "world" })
2. taskDefinition数组的由来
Project类里的task(taskDefinition)方法,参数没有声明类型,按照前面的规则,会把传入的所有参数打包成Object[]数组,也就是taskDefinition数组里包含两个元素:
taskDefinition[0]:字符串"woo"taskDefinition[1]:闭包{ say "hello"; and "world" }
这里需要注意:你提供的代码里写了taskDefinition[0].delegate = task,这其实是个笔误——因为taskDefinition[0]是字符串,不能设置delegate属性,正确的应该是取taskDefinition[1]来处理闭包。
3. 闭包的委托与方法查找逻辑
当代码里设置taskDefinition[1].delegate = task(修正笔误后),并把resolveStrategy设为DELEGATE_FIRST,意味着闭包执行时:
- 优先在委托对象(Task实例)里查找方法,所以
say "hello"会调用Task类的say方法; - 如果委托对象里找不到方法,就去闭包的所有者(Owner)对象里查找,这里的所有者是Project实例,所以
and "world"会调用Project类的and方法。
这样就实现了闭包里同时调用Task和Project的方法的效果。
内容的提问来源于stack exchange,提问作者hilmialf
相关产品推荐
相关产品推荐

