Kotlin擴展函數(shù)和擴展屬性筆記

1. 擴展函數(shù)

Kotlin的擴展函數(shù)可以讓你作為一個類成員進行調(diào)用的函數(shù)假哎,但是是定義在這個類的外部瞬捕。這樣可以很方便的擴展一個已經(jīng)存在的類,為它添加額外的方法舵抹。在Kotlin源碼中肪虎,有大量的擴展函數(shù)來擴展java,這樣使得Kotlin比java更方便使用惧蛹,效率更高扇救。通常在java中,我們是以各種XXXUtils的方式來對已經(jīng)存在的類進行功能的擴展香嗓。但是有了擴展函數(shù)迅腔,我們就能丟棄讓人討厭的XXXUtils方法工具類。下面舉個例子靠娱,假如我們需要為String類型添加一個返回這個字符串最后一個字符的方法:

package com.dengyin2000.kotlintest1

fun String.lastChar(): Char = this.get(this.length - 1)

fun main(args: Array<String>) {
    println("Kotlin".lastChar())
}

你只需要在你添加的函數(shù)名字之前放置你想要擴展的類或者接口的類型钾挟。這個類名叫著接收器類型(receiver type),而你調(diào)用的擴展函數(shù)的值叫做接收器對象(receiver object)饱岸。如下圖:


receiver

接收器類型是擴展定義的類型,而接收器對象是這個類型的實例徽千。調(diào)用方式跟普通的函數(shù)調(diào)用方式一致:

println("Kotlin".lastChar())

在這個例子中苫费,String是接收器類型,"Kotlin"接收器對象双抽,在這個擴展函數(shù)中百框,你可以直接訪問你擴展的類型的函數(shù)和屬性,就像定義在這個類中的方法一樣牍汹,但是擴展函數(shù)并不允許你打破封裝铐维。跟定義在類中方法不同柬泽,它不能訪問那些私有的、受保護的方法和屬性嫁蛇。

1.1 擴展函數(shù)的導(dǎo)入

大多數(shù)情況下锨并,我們直接在包里定義擴展函數(shù)。這樣我們就可以在整個包里面使用這些擴展睬棚,如果我們要使用其他包的擴展第煮,我們就需要導(dǎo)入它。導(dǎo)入擴展函數(shù)跟導(dǎo)入類是一樣的方式抑党。

import com.dengyin2000.kotlintest1.lastChar

或者

import com.dengyin2000.kotlintest1.*

有時候包警,可能你引入的第三方包都對同一個類型進行了相同函數(shù)名擴展,為了解決沖突問題底靠,你可以使用下面的方式對擴展函數(shù)進行改名害晦。

package com.dengyin2000.kotlintest2

import com.dengyin2000.kotlintest1.lastChar as last

fun main(args: Array<String>) {
    println("Kotlin".last())
}

1.2 范型化的擴展函數(shù)

我們也可以在對擴展函數(shù)進行范型化。

package com.dengyin2000.kotlintest1

fun String.lastChar(): Char = this.get(this.length - 1)

fun <T> Collection<T>.joinToString(
        separator: String = ",",
        prefix: String = "",
        postfix: String = ""
): String{
    val result = StringBuilder(prefix)
    for ((index, value) in this.withIndex()) {
        if (index > 0) {
            result.append(separator)
        }
        result.append(value)
    }
    result.append(postfix)
    return result.toString()
}

fun main(args: Array<String>) {
    println(listOf("a", "b", "c").joinToString(prefix = "[", postfix = "]"))
}

輸出:

[a,b,c]

1.3 擴展函數(shù)不可覆蓋(overriding)

方法的覆蓋(overriding)對類中的成員函數(shù)是有效的暑中,但是擴展函數(shù)不能被覆蓋壹瘟,請看下面這個例子:

package com.dengyin2000.kotlintest1

open class View{
    open fun click() {
        println("view clicked")
    }
}

open class Button: View() {
    override fun click(){
        println("button clicked")
    }
}

fun View.longClick() = println("view longClicked")
fun Button.longClick() = println("button longClicked")

fun main(args: Array<String>) {
    val button:View = Button()
    button.click()
    button.longClick()
}

輸出:

button clicked
view longClicked

可以看到擴展函數(shù)并不能被覆蓋,我們把變量定義成View痒芝,longClick()使用的是View.longClick()擴展函數(shù)俐筋。擴展函數(shù)并不是類的一部分,他們申明在類的外部严衬。盡管你可以為某個基類和它的之類用同樣的名字和參數(shù)來定義擴展函數(shù)澄者,被調(diào)用的函數(shù)依賴已被申明的靜態(tài)類型,而不是運行時的變量類型请琳。

1.4 Java調(diào)用擴展函數(shù)

調(diào)用一個擴展函數(shù)并沒有涉及對象的創(chuàng)建或者其他運行時開銷粱挡,在底層,一個擴展函數(shù)是一個接收器對象作為第一個參數(shù)的靜態(tài)方法俄精。這讓我們在java調(diào)用擴展函數(shù)就像調(diào)用靜態(tài)方法一樣询筏,假如我們的擴展函數(shù)定義在com.dengyin2000.kotlintest1.test.kt文件中。那么會生成一個com.dengyin2000.kotlintest1.TestKt.classjava類文件竖慧,其中就包含了我們在Kotlin中定義的那兩個擴展函數(shù)嫌套。如圖:

擴展函數(shù)java

下面就是在Java中調(diào)用Kotlin擴展函數(shù)的方法:

package com.dengyin2000.java;

import com.dengyin2000.kotlintest1.Button;
import com.dengyin2000.kotlintest1.TestKt;
import com.dengyin2000.kotlintest1.View;

public class Test {
    public static void main(String[] args) {
        View view = new Button();
        TestKt.longClick(view);
    }
}

看到這里你應(yīng)該也明白了,為什么擴展函數(shù)不能覆蓋(overriding)了圾旨。

2. 擴展屬性

擴展屬性提供了一種方法用能通過屬性語法進行訪問的API來擴展踱讨。盡管它們被叫做屬性,但是它們不能擁有任何狀態(tài)砍的,它不能添加額外的字段到現(xiàn)有的java對象實例痹筛。不過可以有更簡短的語法在某些時候還是更方便的。

package com.dengyin2000.kotlintest1

val String.lastChar: Char
    get() = get(length - 1)

var StringBuilder.lastChar: Char
    get() =  get(length - 1)
    set(value) {
        this.setCharAt(length -1, value)
    }

fun main(args: Array<String>) {
    println("Kotlin".lastChar)

    val sb = StringBuilder("Kotlin")
    sb.lastChar = 'g'
    println(sb)
}

可以看到擴展屬性也可以通過val或者var定義,然后也是接你需要擴展的類型帚稠,然后屬性名稱谣旁,最后是屬性的類型。var的話可以有set方法定義滋早。你訪問擴展屬性和訪問成員屬性完全一樣榄审。

Kotlin語言基礎(chǔ)筆記

Kotlin流程控制語句筆記

Kotlin操作符重載與中綴表示法筆記

Kotlin擴展函數(shù)和擴展屬性筆記

Kotlin空指針安全(null-safety)筆記

Kotlin類型系統(tǒng)筆記

Kotlin面向?qū)ο缶幊坦P記

Kotlin委托(Delegation)筆記

Kotlin泛型型筆記

Kotlin函數(shù)式編程筆記

Kotlin與Java互操作筆記

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市馆衔,隨后出現(xiàn)的幾起案子瘟判,更是在濱河造成了極大的恐慌,老刑警劉巖角溃,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拷获,死亡現(xiàn)場離奇詭異,居然都是意外死亡减细,警方通過查閱死者的電腦和手機匆瓜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來未蝌,“玉大人驮吱,你說我怎么就攤上這事∠舴停” “怎么了左冬?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵舷嗡,是天一觀的道長落恼。 經(jīng)常有香客問我背镇,道長御滩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任柳畔,我火速辦了婚禮并扇,結(jié)果婚禮上象泵,老公的妹妹穿的比我還像新娘琼腔。我一直安慰自己瑰枫,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布丹莲。 她就那樣靜靜地躺著光坝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪甥材。 梳的紋絲不亂的頭發(fā)上盯另,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機與錄音擂达,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛板鬓,可吹牛的內(nèi)容都是我干的悲敷。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼俭令,長吁一口氣:“原來是場噩夢啊……” “哼后德!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起抄腔,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤瓢湃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后赫蛇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體绵患,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年悟耘,在試婚紗的時候發(fā)現(xiàn)自己被綠了落蝙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡暂幼,死狀恐怖筏勒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情旺嬉,我是刑警寧澤管行,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站邪媳,受9級特大地震影響捐顷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜悲酷,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一套菜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧设易,春花似錦逗柴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至屠尊,卻和暖如春旷祸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背讼昆。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工托享, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓闰围,卻偏偏與公主長得像赃绊,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子羡榴,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容