- 为什么要使用闭包
# 参考
https://juejin.cn/post/6844903878111019022
# 闭包模板
def closure4 = { x, y -> println("x is ${x}, y is ${y}") } // 省略类型
Closure closure6 = { println('Done') } // 声明类型Closure
Closure<Boolean> closure7 = { int a, int b -> a == b } // 可以定义返回类型
# 函数
// def isOdd = { int i -> i%2 != 0 }
// println(isOdd(3))
# 闭包
def isOdd(def i){
return i%2 != 0
}
println(isOdd(3))
# 为什么要使用闭包
Groovy 中的闭包避免了代码的冗长,可以辅助创建轻量级、可复用的代码片段。下面举个简单的例子带大家体验一下闭包的便捷性。
例子:求 1 到 n 之间的所有奇数的和。
传统实现中,我们定义一个 sum 方法,其中使用 for 循环实现奇数的累加,代码如下:
def sum(n) {
total = 0
for (int i = 1; i <= n; i += 2) {
// 计算1到n的奇数和
total += i
}
total
}
println(sum(9)) // n等于9
如果改成计算所有奇数的乘积呢?那又得定义一个 multiply 方法,还是使用 for 循环实现,代码如下:
def multiply(n) {
total = 1
for (int i = 1; i <= n; i += 2) {
// 计算1到n的奇数乘积
total *= i
}
total
}
如果再换成求奇数的平方和呢?实现代码基本与 sum 和 multiply 一致,重复的 for 循环,不同的计算方式而已。
仅仅是三种情况就定义了三个方法,而且存在大量重复代码,这种实现太不优雅了。那使用闭包实现呢?我们只需要定义一个高阶函数,传入一个 Closure 参数即可。
def pickOdd(n, closure) { // 此处的closure可以换成别的参数名
for (int i = 1; i <= n; i += 2) {
// 执行逻辑都由传入的闭包决定
closure(i)
}
}
Groovy 的闭包可以附在一个方法上或者赋值给一个变量。示例中变量 closure 就保持了一个指向闭包的引用。使用 pickOdd 方法的时候传入包含不同逻辑的闭包方法块即可。
// 打印奇数
pickOdd(9) {
println it // 下文会详细介绍it
}
// 求和
total = 0
pickOdd(9, {
num -> total += num // 可以访问total变量
})
println("Sum of odd is: ${total}")
显然,通过闭包实现不仅在语法上比传统方式更优雅,还为函数将部分实现逻辑委托出去提供了一种简单、方便的方式。
- DSL
# 一个DSL脚本就是一个闭包。
https://lesofn.com/archives/shi-yong-groovy-gou-jian-dsl
detailInfo = [:]
def methodMissing(String name, args) {
detailInfo[name] = args
}
def introduce(closure) {
closure.delegate = this
closure()
detailInfo.each {
key, value ->
println "My $key is $value"
}
}
introduce {
name "zx"
age 18
}
- 函数
https://www.w3cschool.cn/groovy/groovy_methods.html
# 没有参数
def methodName() {
//Method code
}
# 带参数
def someMethod(parameter1, parameter2 = 0, parameter3 = 0) {
// Method code goes here
}
- 闭包
https://www.w3cschool.cn/groovy/groovy_closures.html
# 没有参数
def clos = {println "Hello World"};
clos.call();
# 带参数
def clos = {param->println "Hello ${param}"};
clos.call("World");