Kotlin官方文檔中沒有針對Receiver的專題講解沟于,但這個知識點卻貫穿在了整個基礎(chǔ)體系中
Receiver
字面意思是接收者,為什么kotlin會有這個概念?首先kotlin中函數(shù)是一等公民,和java不一樣,java中的函數(shù)(準(zhǔn)確來說是方法)需要依賴于類唧领,kotlin的函數(shù)不依賴類,它可以在任何地方定義雌续,那么在某些場景就會有一些問題
場景1.
開發(fā)者想知道函數(shù)調(diào)用者上下文斩个,看下面代碼
如果函數(shù)有Receiver,那么this 就是對應(yīng)的Receiver,如果不寫Receiver 驯杜,那么this 表示什么受啥?
看到?jīng)],沒寫的話鸽心,默認(rèn)是這個函數(shù)所定義的類里面滚局,那如果我們lambda表達(dá)式里嵌套lambda表達(dá)式,最里層的上下文是哪個呢
與第一層的上下文一致
到這里顽频,我們可以總結(jié)下:
1.函數(shù)默認(rèn)Receiver是該函數(shù)所定義的類內(nèi)(感覺有點廢話)
2.函數(shù)內(nèi)this指向的是Receiver
我這里為什么要講:1.函數(shù)默認(rèn)Receiver是該函數(shù)所定義的類內(nèi) 藤肢。這句廢話,其實是有原因的糯景,
這和kotlin lanbda 表達(dá)式原理有關(guān),具體的可以參看kotlin入門潛修之進(jìn)階篇—高階方法和lambda表達(dá)式原理;kotlin會為lambda表達(dá)式生成一個新類嘁圈,類名為自己所處的類名(Test)+ 所處的方法名(test)+ 數(shù)字(從1開始省骂,有多個則依次遞增)。該類繼承了Lambda類并實現(xiàn)了對應(yīng)的Function接口最住,那按照這個原理钞澳,那么lambda表達(dá)式內(nèi)的this指向的就是編譯器為lambda生成的新類,這與我上面的兩點總結(jié)不符合涨缚,但是上面兩點總結(jié)是根據(jù)事實而來轧粟,這說明在JVM層面,肯定對這種情況作了處理仗岖,至于怎么處理的逃延,我也沒有找到具體的依據(jù)览妖。如果讀者有好的見解還望評論分享下
我這里從Java與kotlin之間的聯(lián)系來解讀下為什么JVM會做這種轉(zhuǎn)換處理以及為什么需要Receiver這個概念
我們知道Java中我們通常說的函數(shù)其實是不準(zhǔn)確的轧拄,應(yīng)該稱為方法,Java中的方法需依賴于類讽膏,java中的this指向的是調(diào)用者本身檩电。因為kotlin(本文討論的kotlin是基于java)是基于Java之上的封裝,所以對于開發(fā)者而言府树,this 不管是在kotlin 還是在java中 概念都應(yīng)該保持統(tǒng)一俐末,即代表上下文,或者說this指向的都是調(diào)用這本身奄侠,但是kotlin 中的函數(shù)是有自己的類型卓箫,或者說它可以自己調(diào)用自己,不需要依賴類垄潮,這樣就會存在一些問題烹卒,那怎樣將kotlin中的this翻譯成Java中的this呢,在轉(zhuǎn)換的時候怎么處理弯洗,這時候就借用了Receiver這個概念了旅急,kotlin可以默認(rèn)或者指定某個函數(shù)的Receiver,這樣類似于對這個函數(shù)做了一份主權(quán)申明:“這個函數(shù)是定義在我這個類的”牡整。這樣做的好處就是在轉(zhuǎn)換成Java語言時可以根據(jù)Receiver來明確上下文this.我們可以在kotlin 字節(jié)碼中找的到了$Receicer 這個常量藐吮。