概述
1.Closures的语法
格式语法:{ [closureParameters -> ] statements }
{ name -> println name }
2.Closures对象和调用
Closures是一个对象(groovy.lang.Closure),是一个匿名代码块,类似于javascript的箭头函数,例子如下
def demo = {
it -> println it
}
def 后紧跟着名称,这名称也是方法名,类似定义一个变量。
Closures调用方式如下
demo(xxx);
demo.call(xxx);
xxx是需要传的参数
3.Closures的参数
Closures的参数分为3种,分别为正常参数,隐式参数和可变参数
1)正常参数
有三个特性,1.类型可选,2.参数名,3.默认值(可选)
例子如下:
def numAdd = { // 类型,默认值
int a, int b=2 -> a+b
}
def numAdd2 = { // 无类型,默认值
a,b=2 -> a+b
}
def numAdd2 = { // 无类型
a,b -> a+b
}
def numAdd3 = { // 有类型
int a, int b -> a+b
}
2)隐式参数
隐式参数:it,这个it指代是传入的参数
代码如下:
def greeting = { it -> "Hello, $it!" }
assert greeting('Patrick') == 'Hello, Patrick!'
// it代表传入的参数
3)可变参数
可变参数与java的可变参数一样,格式如下:type... name
例子如下
def concat1 = { String... args -> args.join('') }
assert concat1('abc','def') == 'abcdef'
def concat2 = { String[] args -> args.join('') }
assert concat2('abc', 'def') == 'abcdef'
4.委托策略
1)Closure的this指代的是什么?
在官网文档中有这样一句话
this
corresponds to the enclosing class where the closure is defined
大概意思,this对应的定义closure的闭包类(最近的)而且只能是类不能是closure,这个不论是内部类还是外部类;
借用官网的例子:
class EnclosedInInnerClass { //例子1
class Inner {
Closure cl = { this }
}
void run() {
def inner = new Inner()
assert inner.cl() == inner
}
}
class NestedClosures { // 例子2
void run() {
def nestedClosures = {
def cl = { this }
cl()
}
assert nestedClosures() == this
}
}
例子1中的this指代的是Inner类,而例子2中this指代的是NestedClosures 。
2)Closure的Owner指代的是什么?
在官网文档中有这样一句话
owner
corresponds to the enclosing object where the closure is defined, which may be either a class or a closure
大概意思,owner对应的创建closure的所有者,这个所有者可能是一个类或者是一个closure
借用官网的例子:
class Enclosing {// 例子1
void run() {
def whatIsOwnerMethod = { getOwner() }
assert whatIsOwnerMethod() == this
def whatIsOwner = { owner }
assert whatIsOwner() == this
}
}
class EnclosedInInnerClass {// 例子2
class Inner {
Closure cl = { owner }
}
void run() {
def inner = new Inner()
assert inner.cl() == inner
}
}
class NestedClosures {// 例子3
void run() {
def nestedClosures = {
def cl = { owner }
cl()
}
assert nestedClosures() == nestedClosures
}
}
例子1中的owner指代的Enclosing类,例子2中的owner指代的是Inner类,例子3中的owner指代的是名为nestedClosures的closure
3)Closure的Delegate指代的是什么?
3.1) Delegate概念
在官网文档中有这样一句话
delegate
corresponds to a third party object where methods calls or properties are resolved whenever the receiver of the message is not defined
大概意思
delegate用于指定第三方对象使用。在一个Closure中使用没有定义的属性或者方法,在调用这个Closure之前,需要使用这个Closure的delegate属性指定一个对象,这个对象需要包含这个Closure之前所使用未定义的属性或者方法,这样整个调用链就完整了。
例子如下:
class Person {
String name
}
class Thing {
String name
}
def p = new Person(name: 'Norman')
def t = new Thing(name: 'Teapot')
def upperCasedName = { delegate.name.toUpperCase() }
upperCasedName.delegate = p
assert upperCasedName() == 'NORMAN'
upperCasedName.delegate = t
assert upperCasedName() == 'TEAPOT'
说明:
第一步:定义两个类Person和Thing,初始化对象p和t,定义一个Closure(upperCasedName)使用delegate的name属性,将值大写。但是delegate属性中并没有name属性。
第二步:将upperCasedName的delegate属性指定p和t,这时调用upperCasedName Closure,会将p和t对象初始化的值大写后返回。
更加直观的例子:
def p = new Person(name:'Igor')
def cl = { name.toUpperCase() }
cl.delegate = p
assert cl() == 'IGOR'
3.2)Delegate的委托策略
委托策略种类:
Closure.OWNER_FIRST默认策略,先在Closure的owner属性中检索Closure使用的方法和属性,找到直接返回,没有找到,再delegate属性中继续寻找。
Closure.DELEGATE_FIRST与Closure.OWNER_FIRST策略逻辑相反,先使用delegate属性,然后使用owner属性。
Closure.OWNER_ONLY 只在 owner属性中检索属性和方法
Closure.DELEGATE_ONLY 只在 delegate属性中检索属性和方法
Closure.TO_SELF用户自定的策略
默认策略例子如下:
class Person {
String name
def pretty = { "My name is $name" }
String toString() {
pretty()
}
}
class Thing {
String name
}
def p = new Person(name: 'Sarah')
def t = new Thing(name: 'Teapot')
assert p.toString() == 'My name is Sarah'
p.pretty.delegate = t
assert p.toString() == 'My name is Sarah'
说明:
没有指定策略时使用默认策略,这个例子中虽然petty的delegate指定了Thing的实例t,但是petty的owner指向person的实例,在owner中找到相应的方法或者属性直接返回了,不在delegate中检索。
指定策略例子如下:
class Person {
String name
int age
def fetchAge = { age }
}
class Thing {
String name
}
def p = new Person(name:'Jessica', age:42)
def t = new Thing(name:'Printer')
def cl = p.fetchAge
cl.delegate = p
assert cl() == 42
cl.delegate = t
assert cl() == 42
cl.resolveStrategy = Closure.DELEGATE_ONLY
cl.delegate = p
assert cl() == 42
cl.delegate = t
try {
cl()
assert false
} catch (MissingPropertyException ex) {
// "age" is not defined on the delegate
}
说明:
在Person定义了fetchAge的Closure后有指定到cl上,cl没有指定策略时,cl的delegate无论指向Person实例p还是Thing实例t,调用的执行结果都是42。这是因为cl的owner指向了p.fetchAge
cl的指定了委托策略只在delegate中检索,cl的delegate执行p时执行没有问题,但是当delegate指向t时出现错误,没有age属性。
5.函数编程
5.1 Currying
currying英文原意是咖喱菜,但是这里的大概意思局部变量设置。
分为三种:LeftCurrying RightCurrying和IndexCurrying
这三种很好理解,例子如下
LeftCurrying:从Closure的参数列表的左侧设置值
def nCopies = { int n, String str -> str*n }
def twice = nCopies.curry(2)
assert twice('bla') == 'blabla'
assert twice('bla') == nCopies(2, 'bla')
RightCurrying:从Closure的参数列表的右侧设置值
def nCopies = { int n, String str -> str*n }
def blah = nCopies.rcurry('bla')
assert blah(2) == 'blabla'
assert blah(2) == nCopies(2, 'bla')
IndexCurrying:
def volume = { double l, double w, double h -> l*w*h }
def fixedWidthVolume = volume.ncurry(1, 2d)
assert volume(3d, 2d, 4d) == fixedWidthVolume(3d, 4d)
def fixedWidthAndHeight = volume.ncurry(1, 2d, 4d)
assert volume(3d, 2d, 4d) == fixedWidthAndHeight(3d)
5.2 结果缓存
Closure的执行结果会缓存起来(使用memoize()方法)(同一个方法,相同的参数,执行的结果相同,不用重新计算一次),以便快速执行;例子如下:
def fib
fib = { long n -> n<2?n:fib(n-1)+fib(n-2) }
assert fib(15) == 610 // 执行的慢
fib = { long n -> n<2?n:fib(n-1)+fib(n-2) }.memoize()
assert fib(25) == 75025 // 执行的快
5.3 Closure组合
多个Closure组合起来,一起使用
例子如下:从大到小执行
def plus2 = { it + 2 }
def times3 = { it * 3 }
def times3plus2 = plus2 << times3 //先执行times3,再执行plus2
assert times3plus2(3) == 11
assert times3plus2(4) == plus2(times3(4))
def plus2times3 = times3 << plus2
assert plus2times3(3) == 15
assert plus2times3(5) == times3(plus2(5))
// reverse composition
assert times3plus2(3) == (times3 >> plus2)(3)
5.4 递归转化(Trampoline方法)
将原来的递归(方法没有执行完成全部堆积到内存中)转换为串行调用,防止出现堆栈溢出错误
例子如下:
def factorial
factorial = { int n, def accu = 1G ->
if (n < 2) return accu
factorial.trampoline(n - 1, n * accu)
}
factorial = factorial.trampoline()
assert factorial(1) == 1
assert factorial(3) == 1 * 2 * 3
至此:Groovy的Closure全部学完,还有一些其他,如Closure嵌套等等。
最后
以上就是震动老鼠为你收集整理的groovy的Closure1.Closures的语法 2.Closures对象和调用3.Closures的参数4.委托策略5.函数编程的全部内容,希望文章能够帮你解决groovy的Closure1.Closures的语法 2.Closures对象和调用3.Closures的参数4.委托策略5.函数编程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复