Context:
DSL (Domain-Specific Language)领域性语言。语言依赖于context(上下文、背景),比如我去拉面馆说“老板,要宽的加个鸡蛋”,我没说是要拉面,老板也知道我的意思了。
with()方法:
JavaScript和VBScript都有with这个特性,支持创建上下文,with作用域内的方法都指向上下文对象。
lst = [1,2]
lst.add(3)
lst.add(4)
println list.size()
println list.contains(2)
等价于:
lst = [1,2]
lst.with{
add(3)
add(4)
println size()
println continas(2)
}
而括号、类型在Groovy中几乎总是可选,所以进一步简化:
lst = [1,2]
lst.with{
add 3
add 4
println size
println continas(2)
}
Groovy拓展:
机制是 调用with方法时,会把闭包的delegate属性设置到 lst 这个对象上。
with是Groovy在Object这个基类上的扩展,除了with还有dump,inspect,sleep。dump可以到处hash、属性(类似于 toString,方法);inspect用于说明创建一个对象需要提供什么,如果没实现则返回toString()的内容;sleep传一个闭包,通过返回值来决定是抑制InterruptedException。还有动态获取属性、调用方法,car.name访问那么属性,动态使用[]操作符,映射到getAt方法,如果位于赋值符左侧则是putAt。代码如下:
class car{
int miles, fuleLevel
}
car = new Car(fulLevel: 80, miles: 25)
properties = ['miles', 'fuelLevel']
properties.each{ name ->
println "$name = ${car[name]}"
}
car[properties[1]] = 100 //same as set method
调用方法是invoke()方法
peter = new Person()
peter.invokeMethod("methodName", null)
peter.invokeMethod("methodName2", 10)
peter.invokeMethod("methodName3", [2, 'uphill'] as Object[])
还有如File的:
new File("path").text //直接显示文件内容
newFile("path").eachLine{ line ->
println line
}
new File('path').filterLine{ it =~ /life/ }
new File('path').withWriter{ file ->
file >> "some data..."
}
当然也可以自定义扩展(在Groovy2.x),通过拓展类、Manifest写,然后加入ClassPath中运行。
创建DSL:
Integer.metaClass{
getDays = { ->
delegate
}
getAgo = { ->
def date = Calendar.instance
date.add(Calendar.DAY_OF_MONTH, -delegate)
date
}
}
Cladendar.metaClass.at = { Map time ->
def hour = 0
def minute = 0;
time.each{key, value ->
hour = key.toInteger()
minute = value.toInteger()
}
delegate.set(Calendar.HOR_OF_DAY, hour)
delegate.set(Calendar.MINUTE, minute)
delegate.set(Calendar.SECOND, 0)
delegate.time
}
println 2.days.age.at(4:30)
//Fri Feb 03 04:30:00 MST 2012