[Learning-Groovy读书笔记]DSL

DSL

Closure with Delegate(设置Closure的delegate)

设置Closure的delegate为某个类, 使得Closure具有了delegate的类的方法。

次方法在Gradle中非常常见, 例如:

package org.gradle.api.artifacts;
... 

public interface Configuration extends FileCollection, HasConfigurableAttributes<Configuration> {
  ....
     Configuration resolutionStrategy(@DelegatesTo(value = ResolutionStrategy.class, strategy = DELEGATE_FIRST) Closure closure);
  ....
}

build.gradle
configurations.all {
  resolutionStrategy {
    // fail eagerly on version conflict (includes transitive dependencies)
    // e.g. multiple different versions of the same dependency (group and name are equal)
    failOnVersionConflict()

    // prefer modules that are part of this build (multi-project or composite build) over external modules
    preferProjectModules()

    // force certain versions of dependencies (including transitive)
    //  *append new forced modules:
    force 'asm:asm-all:3.3.1', 'commons-io:commons-io:1.4'
    //  *replace existing forced modules with new ones:
    forcedModules = ['asm:asm-all:3.3.1']

    // add dependency substitution rules
    dependencySubstitution {
      substitute module('org.gradle:api') with project(':api')
      substitute project(':util') with module('org.gradle:util:3.0')
    }

    // cache dynamic versions for 10 minutes
    cacheDynamicVersionsFor 10*60, 'seconds'
    // don't cache changing modules at all
    cacheChangingModulesFor 0, 'seconds'
  }
}

下面是一个实例:

import groovy.transform.*
import groovy.lang.DelegatesTo
import static groovy.lang.Closure.*

 @Canonical
 class SMS {
     String from, to, body;
     def from(String fromNumber) {
       from = fromNumber
     }
     def to(String toNumber) {
       to = toNumber
     }
     def body(String body) {
      this.body = body
     }
     def send() {
      println "send  $this"
     }
     def static send(@DelegatesTo(strategy=DELEGATE_FIRST, value=SMS.class) Closure closure){
         closure.delegate = new SMS()
         closure()
         closure.delegate.send()
     }
 }
 

 SMS.send{
  from "tom"
  to "peter"
  body "Hello"
 }

执行结果如下:

send  SMS(tom, peter, Hello)

DelegatesTo可设置的参数如下:

  • strategy: 设置Closure中所使用的Property或者method的解析策略。
    解析策略含义
    DELEGATE_FIRST首先尝试在Delegate中解析,之后在Owner
    OWNER_FIRST首先尝试在OWNER中解析,之后在Delegate
    DELEGATE_ONLY只在Delegate中解析
    OWNER_ONLY只在OWNER中解析

Command Chains

通过设定函数的返回值为"this",可以链式调用函数。由于Groovy可省略括号,更加贴近自然语言。例如:

import groovy.transform.*
import groovy.lang.DelegatesTo
import static groovy.lang.Closure.*

 @Canonical
 class SMS {
     String from, to, body;
     def from(String fromNumber) {
       from = fromNumber
     }
     def to(String toNumber) {
       to = toNumber
     }
     def body(String body) {
      this.body = body
     }
     def send() {
      println "send  $this"
     }
     def static send(@DelegatesTo(strategy=DELEGATE_FIRST, value=SMS.class) Closure closure){
         closure.delegate = new SMS()
         closure()
         closure.delegate.send()
     }
 }
 

 SMS.send{
  from "tom"
  to "peter"
  body "Hello"
 }

执行结果如下:

send  SMS(tom, peter, Hello)

Overriding Operators(操作符重载)

通过操作符重载,可以使用操作符(±*/等)来操作领域对象,更加贴近于人们的思考问题的习惯。例如:

class 二十{

 def String toString(){
  return "20"
 }
}
class{
 def static plus(十 a){
     return new 二十()
 }
  def String toString(){
  return "10"
 }
 def static call(){
   return new()
 }
}

println "十 + 十 = ${十 + new 十() }"

执行结果为:

十 + 十 = 20

重载时的Operator和方法的映射关系如下:
在这里插入图片描述

疑问

  1. DelegatesTo的解析策略(strategy)DELEGATE_FIRST和DELEGATE_ONLY貌似没有区别??例如,如下的代码:
 class Test {
     def x = 30
     def y = 40
     def z = 30

     def run() {
         def data = [ x: 10, y: 20 ]
         def cl = { z = z + z }
         cl.delegate = data
         cl.resolveStrategy = Closure.DELEGATE_FIRST
         cl()

     }
 }

 new Test().run()

不管是DELEGATE_FIRST还是DELEGATE_ONLY都会报错。
但是OWNER_FIRST和OWNER_ONLY的动作就和预想的一致。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值