Groovy閉包和DSL

閉包是Groovy的一個非常重要的特性肮柜,可以說他是DSL的基礎陷舅。閉包不是Groovy的首創(chuàng),但是它支持這一重要特性审洞,這就使用我們的代碼靈活莱睁、輕量、可復用芒澜,再也不用像Java一樣動不動就要搞一個類了仰剿,雖然Java后來有了匿名內部類,但是一樣冗余不靈活痴晦。

初識閉包

前面我們講過南吮,閉包其實就是一段代碼塊搂蜓,下面我們就一步步實現(xiàn)自己的閉包乍构,了解閉包的it變量的由來棍鳖。集合的each方法我們已經(jīng)非常熟悉了干签,我們就以其為例,實現(xiàn)一個類似的閉包功能砚尽。

task helloClosure << {    //使用我們自定義的閉包
    customEach {
        println it
    }
}
def customEach(closure){    //模擬一個有10個元素的集合施无,開始迭代
    for(int i in 1..10){
        closure(i)
    }
}

在上面的例子中我們定義了一個方法customEach,它只有一個參數(shù)必孤,用于接收一個閉包(代碼塊)猾骡,那么這個閉包如何執(zhí)行呢?很簡單敷搪,跟一對括號就是執(zhí)行了兴想,會JavaScript的朋友是不是覺得很熟悉,把它當做一個方法調用赡勘,括號里的參數(shù)就是該閉包接收的參數(shù)嫂便,如果只有一個參數(shù),那么就是我們的it變量了闸与。

向閉包傳遞參數(shù)

上一節(jié)我們講了毙替,當閉包有一個參數(shù)時,默認就是it践樱;當有多個參數(shù)是厂画,it就不能表示了,我們需要把參數(shù)一一列出拷邢。

task helloClosure << {    //多個參數(shù)
    eachMap {k,v ->
        println "${k} is ${v}"
    }
}
def eachMap(closure){ 
    def map1 = ["name":"張三","age":18]
    map1.each {
        closure(it.key,it.value)
    }
}

從例子中我們可以看到袱院,我們?yōu)殚]包傳遞了兩個參數(shù),一個key瞭稼,一個value忽洛,便于我們演示。這是我們我們就不能使用it了环肘,必須要顯式的聲明出來脐瑰,如例子中的k,v廷臼,符號->用于把閉包的參數(shù)和主體區(qū)分開來苍在。

閉包委托

Groovy閉包的強大之處在于它支持閉包方法的委托。Groovy的閉包有thisObject荠商、owner寂恬、delegate三個屬性,當你在閉包內調用方法時莱没,由他們來確定使用哪個對象來處理初肉。默認情況下delegate和owner是相等的,但是delegate是可以被修改的饰躲,這個功能是非常強大的牙咏,Gradle中的很閉包的很多功能都是通過修改delegate實現(xiàn)的臼隔。

task helloDelegate << {
   new Delegate().test {
        println "thisObject:${thisObject.getClass()}"
        println "owner:${owner.getClass()}"
        println "delegate:${delegate.getClass()}"
        method1()
        it.method1()
    }
}
def method1(){
    println "Context this:${this.getClass()} in root"
    println "method1 in root"
}
class Delegate {
    def method1(){
        println "Delegate this:${this.getClass()} in Delegate"
        println "method1 in Delegate"
    }
    def test(Closure<Delegate> closure){
        closure(this)
    }
}

運行我們可以看到輸出:

thisObject:class build_e27c427w88bo0afju9niqltzf
owner:class build_e27c427w88bo0afju9niqltzf$_run_closure2
delegate:class build_e27c427w88bo0afju9niqltzf$_run_closure2
this:class build_e27c427w88bo0afju9niqltzf in root
method1 in root
this:class Delegate in Delegate
method1 in Delegate

通過上面的例子我們發(fā)現(xiàn),thisObject的優(yōu)先級最高妄壶,默認情況下摔握,優(yōu)先使用thisObject來處理閉包中調用的方法,如果有則執(zhí)行丁寄。從輸出中我們也可以看到這個thisObject其實就是這個構建腳本的上下文氨淌,他和腳本中的this對象是相等的。

從例子中也證明了delegate和owner是相等的伊磺,他們兩個的優(yōu)先級是owner要比delegate高盛正,所以對于閉包內方法的處理順序是thisObject>owner>delegate。

在DSL中屑埋,比如Gradle豪筝,我們一般會指定delegate為當前的it,這樣我們在閉包內就可以對該it進行配置摘能,或者調用其方法壤蚜。

task configClosure << {
    person {
        personName = "張三"
        personAge = 20
        dumpPerson()
    }
}
class Person {
    String personName    int personAge
    def dumpPerson(){
        println "name is ${personName},age is ${personAge}"
    }
}
def person(Closure<Person> closure){
    Person p = new Person();
    closure.delegate = p    //委托模式優(yōu)先
    closure.setResolveStrategy(Closure.DELEGATE_FIRST);
    closure(p)
}

例子中我們設置了委托對象為當前創(chuàng)建的Person實例,并且設置了委托模式優(yōu)先徊哑,所以我們在試用person方法創(chuàng)建一個Person的實例時,可以在閉包里直接對該Person實例配置聪富,有沒有發(fā)現(xiàn)和我們在Gradle試用task創(chuàng)建一個Task的用法很像莺丑,其實在Gradle中有很多類似的用法,在Gradle也基本上都是使用delegate的方式使用閉包進行配置等操作墩蔓。

DSL

DSL(Domain Specific Language),領域特定語言梢莽,說白了就是專門關注某一領域專門語言,在于專奸披,而不是全昏名,所以才叫領域特定的,而不是像Java這種通用全面的語言阵面。

Gradle就是一門DSL轻局,他是基于Groovy的,專門解決自動化構建的DSL样刷。自動化構建太復雜仑扑、太麻煩、太專業(yè)置鼻,我們理解不了镇饮,沒問題,專家們就開發(fā)了DSL—Gradle箕母,我們作為開發(fā)者只要按照Gradle DSL定義的储藐,書寫相應的Gradle腳本就可以達到我們自動化構建的目的俱济,這也是DSL的初衷。

DSL涉及的東西還有很多钙勃,這里我們簡單的提一下概念蛛碌,讓大家有個了解,關于這方便更詳細的可以閱讀世界級軟件開發(fā)大師Martin Fowler的《領域特定語言》肺缕,這本書介紹的非常詳細左医。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市同木,隨后出現(xiàn)的幾起案子浮梢,更是在濱河造成了極大的恐慌,老刑警劉巖彤路,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件秕硝,死亡現(xiàn)場離奇詭異,居然都是意外死亡洲尊,警方通過查閱死者的電腦和手機远豺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坞嘀,“玉大人躯护,你說我怎么就攤上這事±錾” “怎么了棺滞?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長矢渊。 經(jīng)常有香客問我继准,道長,這世上最難降的妖魔是什么矮男? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任移必,我火速辦了婚禮,結果婚禮上毡鉴,老公的妹妹穿的比我還像新娘崔泵。我一直安慰自己,他們只是感情好猪瞬,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布管削。 她就那樣靜靜地躺著,像睡著了一般撑螺。 火紅的嫁衣襯著肌膚如雪含思。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機與錄音含潘,去河邊找鬼饲做。 笑死,一個胖子當著我的面吹牛遏弱,可吹牛的內容都是我干的盆均。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼漱逸,長吁一口氣:“原來是場噩夢啊……” “哼泪姨!你這毒婦竟也來了?” 一聲冷哼從身側響起饰抒,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤肮砾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后袋坑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仗处,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年枣宫,在試婚紗的時候發(fā)現(xiàn)自己被綠了婆誓。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡也颤,死狀恐怖洋幻,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情翅娶,我是刑警寧澤文留,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站故觅,受9級特大地震影響,放射性物質發(fā)生泄漏渠啊。R本人自食惡果不足惜输吏,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望替蛉。 院中可真熱鬧贯溅,春花似錦、人聲如沸躲查。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽镣煮。三九已至姐霍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背镊折。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工胯府, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人恨胚。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓骂因,卻偏偏與公主長得像,于是被迫代替她去往敵國和親赃泡。 傳聞我的和親對象是個殘疾皇子寒波,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)升熊,斷路器俄烁,智...
    卡卡羅2017閱讀 134,699評論 18 139
  • 努力的人,應該像好色那樣好學 做Android開發(fā)的同學僚碎,對Gradle肯定不陌生猴娩,我們用它配置、構建工程勺阐,可能還...
    HitenDev閱讀 13,412評論 9 50
  • 本文介紹了Groovy閉包的有關內容卷中。閉包可以說是Groovy中最重要的功能了。如果沒有閉包渊抽,那么Groovy除了...
    樂百川閱讀 7,605評論 3 13
  • 這篇文章講給大家?guī)韌radle打包系列中的高級用法-自己動手編寫gradle插件蟆豫。我們平常在做安卓開發(fā)時,都會在...
    呆萌狗和求疵喵閱讀 15,989評論 22 80
  • 學習Gradle懒闷,前前后后總結了一些內容十减,然后整理出了一個系列,共計10篇文章愤估,與大家分享: Groovy基本介紹...
    sososeen09閱讀 1,829評論 0 7