給 Gradle 入門者的 Groovy 語言特性介紹

這篇文章目標群眾並非已經熟悉 Groovy 語言的朋友們,不過若是不吝指教的話也歡迎讀完,指出可能有錯誤的地方(畢竟這都是筆者自己從書上看來的),或是筆者遺漏了什麼為了學習 Gradle 所需了解的 Groovy 的重要特性的話,也歡迎補充指教 :)

由於盧育聖 (Sam Lu)老師在 Facebook 上貼的這篇文章:

就像是一盞明燈一樣點亮了 Android 開發者學習 Gradle 的康莊大道啊!一點都不誇張!

所以翻了翻目前市面上有的書籍,決定先挑本「Gradle in Action」來看,這本書在附錄的章節有介紹一些要認識 Gradle 所需具備的 Groovy 的基礎,個人覺得還不錯,以下是這個章節個人的幾點筆記:


  • 比起 Java 在每個敘述的結尾必須使用 ; 來結束該敘述,Groovy 在這點是 Optional 的

  • 在 Groovy 中的每個類別 (Class)、建構子 (Contructor) 以及方法 (Method) ,其預設的 Scope 都是 Public

  • 在 Groovy 中,方法中的最後一個描述 (expression) 會用來作為該方法的回傳值;也就是說 return 敘述在 Groovy 中也是 Optional 的

  • Groovy 的編譯器會自動幫我們加上 fields 的 getter/setter 方法,故無需自行撰寫

  • 在 Groovy 中,類別的 fileds 可以透過 . (dot-notation) 來存取,就好比 Java 中的 public fields;只不過實際上 Groovy 是透過編譯器自動產生的 getter/setter 方法來存取

  • 如果在 Groovy 中利用 == 來比較兩個類別的實例 (instance),Groovy 會自動呼叫實例的 equals() 方法;利用這個操作子來比較類別實例也能夠避免 NullPointerException 的問題

  • Java 是個強資料型別 (strong data typing) 的語言,相較之下,在 Groovy 中,變數的資料型態、方法的參數型態以及方法回傳值的資料型態的宣告都是可以透過簡單的 def 關鍵字來標示,它是一個 java.lang.Object 的 Placeholder,在執行期間,Groovy 會根據所賦的值來決定其型態應該為何,也因此 Groovy 是個有如 Ruby、Python 以及 Perl 特性的動態語言;當然,在一些譬如公開 API 的情況下,我們還是可以使用強資料型別的宣告,這樣一來除了達到說明 API 參數型別的文件般效果之外,還能夠使得我們在編譯階段就能夠得知是否有錯誤

  • 在方法簽名具有一個或一個以上的參數時,Groovy 可以省略方法的括號 (Parentheses)

  • Groovy 中有三種宣告 String 的方式:

    • 任何使用 單引號 所標示的都是字串
      def myString1 = 'This is a single-quoted String'
      
    • 像傳統 Java 使用 雙引號 風格的字串
      def myString2 = "This is a double-quoted String"
      
    • 採用 三個雙引號 風格的可跨行的字串(用來編寫 SQL 語法時特別有用)
      def myString3 = """
      This
      is a
      multiline
      String
      """
      
  • 第二種利用雙引號標示的字串又稱為 Groovy String(GString),與一般 Java 的 String 不同,可以在字串中安插由 (dollar sign) 或是 ${} (dollar sign and curly braces) 所表示的變數,在執行期間,Groovy 將會自動解析這些 placeholder 所表示的字串內容,並轉換、組合出最終的字串,頗有 Perl 字串的感覺

    def language = 'groovy'
    def sentence = "$language is awesome!"
    def improvedSentence = "${language.capitalize()} is awesome!"
    
  • Groovy 的 List 可以直接使用 [] 實例化出 java.util.ArrayList 物件;並且能夠利用 << 運算子來添加元素至既有的 List 中

    def buildTools = ['Ant', 'Maven']
    assert buildTools.getClass() == java.util.ArrayList
    assert buildTools.size() == 2
    assert buildTools[1] == 'Maven'
    // add element to ArrayList
    
    buildTools << 'Gradle'
    assert buildTools.size() == 3
    assert buildTools[2] == 'Gradle'
    buildTools.each { buildTool -> println buildTool }
    
  • Groovy 的 Map 也一樣可以透過 [key:value] 的表示方式,來實例化出 java.lang.LinkedHashMap 的物件,直接加入新的 key/value 配對便可新增元素至既有的 Map 中

    def zipCodes = ['中正區':100, '大同區':103, '中山區':104]
    assert zipCodes.size() == 3
    assert zipCodes['中山區'] == 104
    zipCodes['文山區'] = 116
    assert zipCodes.size() == 4
    
  • Closures in Groovy,Closure (好像有人翻譯成閉包吧!)是一個型別為 groovy.lang.Closure 的區塊程式碼,類似其他語言的 Lambda 表示法;Closure 可以被變數參考、作為方法參數傳入或是當做普通方法來呼叫都可以。

  • Implicit Closure Parameter -- 任何未明確定義任何參數的 Closure 都能夠存取一個名為 it 的內部變數,這個變數會參考到當該 Closure 被呼叫時所傳入該 Closure 的第一個參數;若並無傳入的參數,則該 it 變數的值會是 null

    def addPoint {
    //implicit parameter it here
    
    it.points++
    }
    
  • Explicit Closure Parameter -- 我們也可以明確的定義 Closure 的參數名稱(Closure 並未限制本身所能定義的參數數量)

    def addPoint { Score score -> // typing of score is optional
    
    score.points++
    }
    
  • Closure 永遠都有回傳值,當沒有明確使用 return 時,Closure 中的最後一個敘述會被用來作為回傳值;而當使用 return 敘述時,則回傳 return 敘述的值。若 Closure 中的最後一個敘述沒有值的話,則回傳 null

  • Closure 作為方法參數:

    Integer incrementVersion(Closure closure, Integer count) {
    closure() + count //get the return value of the passed in Closure then add
    
    }
    ProjectVersion projectVersion = new ProjectVersion(major: 1, minor: 10)
    assert incrementVersion({ projectVersion.minor }, 2) == 12
    
  • Gradle 是一個由 Groovy 寫成的 DSL (Domain Specific Language),這也意味者 Gradle 的語法必須遵照 Groovy 的語法規範,否則便會在執行時期報錯;另外也意味著,我們可以在 Gradle 中使用 Groovy 所提供的任何語法。

  • 每個 Gradle 的 build script 至少關連至一個 org.gradle.api.Project 的實例。絕大部分的情況下,我們在 Gradle 腳本中所調用的屬性 (properties) 與方法 (methods) 都自動地委派給 Project 實例了。

總合上述幾點,再回顧一下 Gradle 中的語法,然後看看下面這張圖例,現在是不是對對 Gradle 比較有概念了呢?


圖片出處:Gradle in Action


BTW, 要練習寫 Groovy 不見得要安裝 Groovy 的 runtime,可以利用線上的 Groovy Web Console 來練習 Groovy

comments powered by Disqus