作为一个近乎渣渣的七年经验程序员,回乡我的新工作竟然又是一门新语言和新框架。能学一点是一点吧。
<hr>
跟着Grails Getting Started-II这本书的流程学
1、创建项目
我在F盘建立了一个web目录
然后在web目录下create-app racetrack
然后Grails帮我在web目录下新建了一个项目叫racetrack
这时候我把命令行cd到racetrack目录下,输入grails run-app
程序就能运行起来了
2、创建MVC
domain就是M
命令行输入grails create-domain-class Race,grails create-domain-class Registration
Grails帮我在domain/racetrack文件夹下创建Race.groovy,Registration.groovy文件
我照书上给这俩类添加了一些属性
是引用其他对象的集合,前两个引用对象,后一个引用整型值。他们都能动态增长,列表通过整型值索引,映射用任意类型值索引。
列表(list)
def numbers = [11,12,13,14]
索引可以使用负数,表示从末端开始向前。
numbers[3]实质上就是numbers.getAt(3)
numbers[0..2] //返回列表[11,12,13],表示包含边界的索引范围
numbers[0..<2] //返回列表[11,12],表示不包含边界的索引范围
通过<<运算符可以把一个新元素追加到列表的最后
使用+运算符可以连接两个列表
numbers+[15,16] //返回列表[11,12,13,14,15,16]
-操作符从列表中删除元素
numbers-[13] //返回列表[11,12,14]
列表的方法
add :一个参数是在末尾追加新值,两个参数的话第一个参数指定位置
addAll:
contains:如果该列表包含指定值就返回true
get:返回当前列表中指定位置的元素值
isEmpty:如果当前列表没有元素返回true
remove:删除指定的元素,参数可以是下标,也可以是首次出现的给定元素,当元素是数值型时,不能通过元素删除,会出现越界异常(out-of-bound)
size,返回一个整数,表示元素个数
以下是GDK新增
flatten:使当前列表元素形式一致并返回一个新列表
getAt:和get一个样,这个是GDK新增的,区别只是这个能复数索引,能通过范围返回新列表
intersect:返回一个新列表,其值为原始列表和输入列表的所有元素
leftShift:重载左移运算符,提供一个像列表添加新值得简单方法
minus:生成一个新列表,元素由原始列表中那些不包含在参数collection中的值组成
plus:生成一个新列表,参数可以是值也可以是列表
pop:删除当前列表中最后一个值元素
putAt:赋值语句支持下标运算符
reverse:返回原列表倒序
sort:返回原始列表排序副本
映射(map)
一种引用对象的无序集合,映射中元素可以根据关键字访问,关键字可以是任意类型,映射的值可以为空。
范例:
['Ken':'Barclay','John':'Savage'] 姓/名集合
[4:[2],6:[3,2],12:[6,4,3,2]] 整形关键字及其约数列表
[:] 空映射
如果关键字是变量名,就解释成String
def x=1
def y=2
def m = [x : y , y : x]
于是m就是映射:
m=['x' : 2, 'y' : 1]
映射中增加一个元素如下
library['Sally']=['Basic']
映射的方法:
containsKey:
get:根据Key找Value,第二个参数可选,可以放默认值,如果没有找到对应的key则返回默认值,没放默认值得话,没找到返回空。
keySet:返回当前映射的一组关键字(Set类型),可以用来遍历映射。
getAt:
put:第一个参数放Key,第二个参数放Value,都是对象类型。
size:
values:返回当前映射中所有值得结合,类型是Collection
范围(range)
范围是表达特定序列值得简略方法。通过雪烈中第一个值和最后一个值表示,范围可以是倒序,也可以用<表示不包含边界
1900..1999 //20世纪包含边界
2000..<2100 //21世纪(不包含边界)
'A'..'D' //A,B,C,D
10..1 //10,9,....,1
'Z'.. 'X' // Z,Y和X
范围可以根据下标访问
def reversedTen = 10..1
reversedTen[2] //8
这个例子表示范围的升序降序可以通过整型表达式表示:
def start = 10
def finish = 20
start..finish + 1 //[10~21]
范围的方法:
contains:如果当前范围包含元素则返回true
get:返回当前范围中给定位置的元素
getFrom/getTo:获取当前范围中下标最大最小的元素
isReverse:当前范围是否为逆序
size:
subList:取之间的值,不包含toIndex
1.定义一个方法
Groovy中定义一个方法关键字还是def
def greetings(){
print "Hello and welcome"
}
greetings()
2.在一行中使用多个语句用分号分开
def greetings(){
print "Hello e"; print "and welcome"
}
greetings()
3.方法参数
Groovy是弱类型语言,所以方法签名中的参数没有类型,只有名称
def greetings(name){
print "Hello e"; print "and welcome ${name}"
}
greetings("John")
多个参数用逗号分隔,可以有默认值,
def someMethod(para1,para2 = 0,para3 = 0
){
}
4.方法返回值
在方法签名上没有体现,在方法体重直接用retrun返回就可以了
5.隐式返回值
其实 就是return语句是可以不写的,最后一句语句的值就是返回值
6.参数传递
Groovy没有引用传递和值传递之分,只有传值方式,也就是java的值传递。
也就是说在方法内部修改变量,外侧的变量不受影响。
集合(列表、映射、范围也可以作为方法的参数和返回值)
7.作用域
在方法内定义的变量,只能在方法内使用,方法外部不能访问。
另外Groovy入门经典这本书说,在方法内部不能访问方法外的变量,但是,在Groovy2.4.3环境下亲测是可以访问的。大概老版本不能访问吧。
8.断言
跟java一样也是assert()方法,比如
assert('1'=='1')
如果断言为真,不输出任何结果,如果断言为假则抛出一个异常
类似这样
|
false
at test.run(test.groovy:6)
8.while语句
直到括号里面的值为false时终止循环
def LIMIT =10
def count =1
println 'Start'
while(count <=LIMIT){
println "count:${count}"
count++
}
println 'Done'
9.for语句
Groovy的for语句只能使用in关键字,in前面是值,in后面可以是列表、映射、范围、字符串
def LIMIT =10
println 'Start'
for(count in 1..LIMIT){
println "count:${count}"
count++
}
println 'Done'
以上的意思就是从1开始循环到10,确实代码量变少,功能更清晰了。
10.if语句
Groovy的if语句和javaScript,java一模一样
11.switch语句
也和
javaScript,java一模一样,只是case中可以是列表、映射、范围、字符串,正则表达式
当然列表的时候只要一个符合就可以,字符串要整句匹配上才可以。
12.break和continue语句
与java没有区别
简而言之,Groovy闭包就是将方法定义成变量。
入门经典对Groovy的闭包定义的很清晰且深入浅出,原文摘录如下
Groovy闭包是以后总表示可执行代码块的方法。闭包也是对象,可以像方法一样传递参数。由于闭包是代码块,因此也可以在需要时执行。像方法一样,在定义的过程中,闭包可以使用一个或者多个参数。闭包的一个重要的特有属性就是,它们可以访问属性信息。这就意味着在声明闭包之后,闭包可以使用并修改其作用域内的所有变量值。
闭包最常用的用途是处理集合,比如可以遍历没然后将闭包应用到每个元素上,闭包是Groovy能简化脚本开发的一个重要原因。
闭包及其调用方法(call是可以省略的)
def clos = {param -> println "Heool ${param}"}
clos.call('word');
clos('again')
param ->也是可以省略的,称为隐参数用it代替,显然只有一个参数的时候才能这样
def greeting = 'Hello'
def clos = { println "${greeting} ${it}"}
clos.call('word')
greeting = 'Welcome'
clos.call('word')
通过闭包改变方法外属性值
def greeting = 'Hello'
def clos = {param -> println "${greeting} ${param}"}
clos.call('word')
greeting = 'Welcome'
clos.call('word')
输出是
Hello word
Welcome word
这里做了个是实验,江闭包放到最后,发现报错了,可见闭包跟javascript的对象话的方法不一样,javascript的方法对象,总是首先被读入内存的。
将闭包作为方法参数
def greeting = 'Hello'
def clos = {param -> println "${greeting} ${param}"}
clos.call('word')
greeting = 'Welcome'
clos.call('word')
def demo(clo){
def greeting ='bonjour'
clo.call('Ken')
}
demo(clos)
如果方法调用的最后一个参数是闭包,可以把闭包写到括号后面、
demo(clos)
demo()
clos
def greeting = 'Hello'
def clos = {param -> println "${greeting} ${param}"}
def demo(clo){
def greeting ='Bonjour'
clo.call('Ken')
}
//demo()clos
demo(){param -> println "Welcom ${param}"}
demo clos
demo {param -> println "Welcom ${param}"}
最后两句代码调用demo方法并江必报作为实参,倒数第二句代码调用闭包对象,倒数第一句代码调用
闭包自面值,这两种方法都省略了方法的括号
注释掉那句代码运行时报错,对比一下后一句,可以看出当有括号时,只能使用闭包自面值,不能调用闭包对象。
使用闭包求阶乘
def factorial = 1
1.upto(2){num -> factorial *= num}
println "Factorial(5):${factorial}"
println "${1.upto(5){}}"
结果是
Factorial(5):120
null
这里每次调用
upto方法时都从字面值1开始,一直循环到给定参数5后面的闭包也就执行了五次
闭包用在集合和字符串上
[1,2,3,4].each{print it}
打印结果是
1234
Result: [1, 2, 3, 4]
Groovy有很多方法是利用闭包的,我就不一一写了。
类
举个栗子
class Account{
def number
def balance
def credit(amount){
balance += amount
}
def debit(amount){
if(balance >= amount)
balance = amount
}
def display(){
println "Account ${number} with balance ${balance}"
}
}
def acc = new Account(number:'ABC123',balance:1200)
acc.display()
acc.credit(200)
acc.display()
输出是:
Account ABC123 with balance 1200
Account ABC123 with balance 1400
除了初始化类的方式之外,和java语法貌似没有什么不同。可以想象实现方式一定是java的getter和setter方法。
构造器
Groovy中也可以显式的声明构造方法,用来初始化类的属性。
构造器和方法的最大区别在与构造器名和类名相同。
class Account{
def number
def balance
def Account(number ,balance){
this.number = number
this.balance = balance
}
def credit(amount){
balance += amount
}
def debit(amount){
if(balance >= amount)
balance = amount
}
def display(){
println "Account ${number} with balance ${balance}"
}
}
//def acc = new Account(number:'ABC123',balance:1200)
def acc = new Account('ABC123',1200)
acc.display()
acc.credit(200)
acc.display()
这样一来Groovy的类同java的类就非常像了。