作為一個近乎渣渣的七年經驗程式員,回鄉我的新工作竟然又是一門新語言和新架構。能學一點是一點吧。
<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)映射(map)範圍(range) 是引用其他對象的集合,前兩個引用對象,後一個引用整型值。他們都能動态增長,清單通過整型值索引,映射用任意類型值索引。
清單(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的類就非常像了。