Groovy基础知识二

十七、特征
特征可以认为是有实现方法的接口,使用trait 关键字声明。特征可以实现接口,使用implement关键字;特征之间可以继承,使用extends关键字。
例子1:声明了一个为水果的特征,有默认的实现(购买方法):

trait Fruit {
       void buy() {
           println "5元一斤"
       }
   }

例子2:为食物的一个特征

 trait Food {
       void eat() {
           println "吃面食"
       }
   }

十八、闭包
1.闭包简单介绍
闭包是一个短的匿名代码块,一个方法甚至可以将代码块作为参数。它们是匿名的。闭包也使用参数和外部变量。
例子1(无参数闭包):

 def closer = { println "这是一个闭包" }

例子2(有参数闭包):

def closer2 = { name -> println name }

如果闭包参数只有一个的情况下,参数可以省略,使用闭包中的隐式参数it代替:

def closer3 = { it -> println it }

闭包中参数的类型定义是可选的。如果没有指定参数的类型,那么编译器会自动推断出来。在例子2,如果没有传入参数的话,
那么输出结果就是null。

2.闭包调用
在没有参数的情况下调用闭包:
闭包名称.call()。或者简写成:闭包名称()。如:

def closer = { println "这是一个闭包" }
closer.call() //或者 closer()

如果闭包需要传递参数,则需要在调用的时候给定参数:

def closer = { name -> println name }
closer.call("哈哈哈") //或者 closer("哈哈哈")

3.闭包的返回值
通常情况下,以return关键字声明表示返回值。如果没有return语句,那么闭包的返回值是以闭包内最后一行语句作为返回值的。

def a = { int i -> ++i}
println a(1)  //输出结果为 2

def d = {it -> return ++it}
println d(1)  //输出结果为 2

4.闭包集合
这个不是闭包内官方的定义,这完全是个人的说法。就是声明一个闭包对象包含了多个闭包而已。它的写法类似写一个Map映射:[ 闭包名称:闭包实现 ],多个闭包使用逗号,分割。

def e = [fun1:{ println "第一"},
         fun2:{name -> println "${name}第二"}]
 e.fun1()
 e.fun2("小明")

5.闭包作为方法参数
在Groovy中,很多用于数据类型(例如列表和集合)的内置方法都有闭包作为参数类型。

 def lst = [11, 12, 13, 14];
      lst.each {println it}

常规下使用闭包作为参数:

//声明一个方法出来,分别传入一个闭包参数跟一个常规参数。
static void fun1(Closure c, int b) {
    println(b + c())
}
//调用形式:
fun1({4}, 4)  //输出结果是 8.

当闭包作为参数列表最后一个参数时,可以将闭包移出到参数列表外面显得更加美观:

static void fun3(int a,int b,Closure c) {
    println (a+ b+ c())
}

fun3(3,3){
    100/2
}            //输出结果为56。

当然,闭包作为参数时也不是必须声明 Closure c;直接使用参数名称也是可以的。因为groovy是可以自动转换类型的。

static void fun4(a, int b, c) {
    print(a + b - c())
}
fun4(4,4){
    return 2
}             //输出结果为 6,这里自动识别a为int,c为闭包了

6、委托
委托策略是groovy中闭包独有的语法,这也使得闭包较java的lambda更为高级。在闭包中有3个很重要的属性:

  • this:表示闭包的外围类,即最近的外层类,不能是闭包。用getThisObject()获取
  • owner:表示闭包的直接外围对象,可以是类也可以是闭包。用 getOwner()获取
  • delegate:指定一个第三方类来调用,指定后,这个闭包就属于这个第三方类,可以使用getDelegate()获取
def closer4 = {
    println "this= ${this}, ${getThisObject()}"
    println "owner= ${owner}, ${getOwner()}"
    println "delegate= ${delegate}, ${getDelegate()}"
}
closer4.call()
<!--输出结果:-->
<!--this= test@72c8e7b, test@72c8e7b-->
<!--owner= test@72c8e7b, test@72c8e7b-->
<!--delegate= test@72c8e7b, test@72c8e7b-->

上面执行3的对象结果都是一样的,是因为全写在一个类上里面的。下面修改一下:

 class demo {
    def c1 = {
        println "this= ${this}"
        println "owner= ${owner}"
    }
   void fun1(){
        c1()
        new demo2().fun2()
    }
    class demo2 {
        def c2 = {
            println "this= ${this}"
            println "owner= ${owner}"
        }
       void fun2(){
            c2()
        }
    }
}
def demo = new demo()
demo.fun1()
/*
输出结果:
this= demo@55de24cc
owner= demo@55de24cc

this= demo$demo2@7e990ed7
owner= demo$demo2@7e990ed7
*/

这里2次的输出结果是不一样的。第一次的this,owner指向demo对象;第二次则是指向demo2的对象。this,owner都是指向最近类(owner可以是闭包)的,而delegate则是由第三方类使用,需要手动指定。
7、delegate策略
先搞清楚这个策略的概念:在闭包中,属性没有指明其所有者的时候,delegate策略就会发挥作用。以下是delegate的几种策略机制:

  • Closure.DELEGATE_FIRST:优先从delegate中寻找属性或方法,找不到再从owner中寻找;
  • Closure.DELEGATE_ONLY:只在delegate中寻找;
  • Closure.OWNER_FIRST: 这是默认的策略,优先从owner中寻找属性或方法,找不到再从delegate中寻找;
  • Closure.OWNER_ONLY:只在owner寻找;
  • Closure.TO_SELF:在闭包里面寻找;
    举例子:
class A {
    private String color
    private String weight
    private String size

    A(String color = "", String weight = "", String size = "150cm") {
        this.color = color
        this.weight = weight
        this.size = size
    }
    def fun0 = {
        println "A:外围类:${getThisObject()}"
        println "A:this= ${this}"
        println "A:owner= ${owner}"
        println "A:delegate= ${delegate}"
    }
    def fun1 = {
        println "$color, $weight"
    }
    def fun2 = {
        println size
    }
}
A newA = new A("红色", "100")
newA.fun2()

def c1 = {
    println size
}
c1()

声明了一个内部类A,有3条属性以及若干个闭包。类外部有一个闭包c1,只是输出了size。分别执行内部类A的fun2与外部闭包c1。结果是类A输出了150cm。
而c1()却抛出异常了:Caught: groovy.lang.MissingPropertyException: No such property: size for class: test。很明显,它说test类没有size这个属性。首先c1闭包中的size并没有指定所有者,会触发delegate策略,先在它的owner中(test类)寻找,没有找到后,发现也没有使用委托。于是抛出异常。修改代码:

c1.delegate = newA
c1()

将c1委托给A的示例后,执行c1,程序没有抛出异常并且输出结果为: 150cm。再修改代码,手动设置委托策略:

c1.resolveStrategy = Closure.OWNER_ONLY 
c1.delegate = newA
c1()

此时委托策略只能从owner中寻找。结果抛出异常:Caught: groovy.lang.MissingPropertyException: No such property: size for class: test,再看个例子,
添加一个类B:

class B {
    private String color
    private String weight

    B(String color = "", String weight = "") {
        this.color = color
        this.weight = weight
    }

    def fun1 = {
        println "$color, $weight"
    }
}
B newB = new B("绿色","200")

newA.fun1.delegate = newB
newA.fun1()

实例化另一个内部类B对象 newB,并且将类A中的闭包fun1委托给B对象。结果却是:A中的属性:红色, 100 。可能会有疑问:fun1委托给了B对象,但是类B中也有color跟weight属性,为什么输出的确实A累中的color跟weight?这里还是委托策略的原因。fun1确实是委托给了B的实例。但是使用的还是默认下的策略:优先从owner中寻找属性或方法,找不到再从delegate中寻找。fun2的owner自然是类A,A中拥有size属性,就不会再往委托下去找了,而是输出结果。OK,修改fun1的委托策略:

newA.fun1.resolveStrategy = Closure.DELEGATE_FIRST 

输出结果为:绿色, 200。好了这会是B类中的color与weight了。使用的是A类fun1,使用了委托后,结果确实B类的属性,这就是委托策略的用处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值