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和方法的映射关系如下:
疑问
- 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的动作就和预想的一致。