Kotlin 知識(shí)梳理(2) - 函數(shù)的定義與調(diào)用

Kotlin 知識(shí)梳理系列文章

Kotlin 知識(shí)梳理(1) - Kotlin 基礎(chǔ)
Kotlin 知識(shí)梳理(2) - 函數(shù)的定義與調(diào)用
Kotlin 知識(shí)梳理(3) - 類豆茫、對(duì)象和接口
Kotlin 知識(shí)梳理(4) - 數(shù)據(jù)類注竿、類委托 及 object 關(guān)鍵字
Kotlin 知識(shí)梳理(5) - lambda 表達(dá)式和成員引用
Kotlin 知識(shí)梳理(6) - Kotlin 的可空性
Kotlin 知識(shí)梳理(7) - Kotlin 的類型系統(tǒng)
Kotlin 知識(shí)梳理(8) - 運(yùn)算符重載及其他約定
Kotlin 知識(shí)梳理(9) - 委托屬性
Kotlin 知識(shí)梳理(10) - 高階函數(shù):Lambda 作為形參或返回值
Kotlin 知識(shí)梳理(11) - 內(nèi)聯(lián)函數(shù)
Kotlin 知識(shí)梳理(12) - 泛型類型參數(shù)


一、本文概要

本文是對(duì)<<Kotlin in Action>>的學(xué)習(xí)筆記粉怕,如果需要運(yùn)行相應(yīng)的代碼可以訪問(wèn)在線環(huán)境 try.kotlinlang.org,這部分的思維導(dǎo)圖為:

二袱蜡、在 kotlin 中創(chuàng)建集合

kotlin中,創(chuàng)建HashSet秤掌、ArrayListHashMap的方法如下:


通過(guò)打印這些集合的類型,可以看到是采用的標(biāo)準(zhǔn)的Java集合類:

這么做的原因鹰霍,是因?yàn)槭褂脴?biāo)準(zhǔn)的Java集合使kotlin可以更容易地與Java代碼交互闻鉴。當(dāng)從Kotlin調(diào)用Java函數(shù)的時(shí)候,不用轉(zhuǎn)換它的集合類來(lái)匹配Java的類茂洒,反之亦然孟岛。

在這些集合對(duì)象上,我們除了可以使用Java當(dāng)中定義的基本函數(shù)以外督勺,還可以使用kotlin提供的擴(kuò)展方法渠羞,例如下面的lastmax


運(yùn)行結(jié)果為:

三、讓函數(shù)更好調(diào)用

下面智哀,我們定義一個(gè)函數(shù)次询,它的作用的是打印集合當(dāng)中的元素,并指定元素之間添加分隔符瓷叫、前綴和后綴:



運(yùn)行結(jié)果為:


3.1 命名參數(shù)

在上面的例子中屯吊,我們指定了分隔符、前綴和后綴三個(gè)參數(shù)摹菠,但是對(duì)于這個(gè)函數(shù)的使用者來(lái)說(shuō)雌芽,如果不去看這些函數(shù)的聲明,很難看出這些String類型的含義辨嗽,這時(shí)候就可以使用 命名參數(shù) 的方法來(lái)調(diào)用,這有兩點(diǎn)好處:

  • 增加函數(shù)的可讀性
  • 以想要的順序指定需要的參數(shù)

下面淮腾,我們使用命名參數(shù)糟需,并在不改變函數(shù)定義的情況下,改變傳入?yún)?shù)的順序谷朝,也可以得到和上面相同的運(yùn)行結(jié)果:


對(duì)于命名參數(shù)洲押,有以下幾點(diǎn)需要注意:

  • 如果在調(diào)用一個(gè)函數(shù)時(shí),指明了一個(gè)參數(shù)的名稱圆凰,那它之后的所有參數(shù)都要表明名稱杈帐。
  • 當(dāng)調(diào)用Java函數(shù)時(shí),不能使用命名參數(shù)专钉。

3.2 默認(rèn)參數(shù)值

kotlin中挑童,可以在聲明函數(shù)的時(shí)候,指定參數(shù)的默認(rèn)值跃须,這樣就可以避免創(chuàng)建重載的函數(shù)站叼,例如上面的例子,我們可以在 定義函數(shù) 時(shí)菇民,指定三個(gè)String的默認(rèn)值尽楔,而在 調(diào)用函數(shù) 的時(shí)候投储,如果沒(méi)有傳遞這些參數(shù),那么將會(huì)采用默認(rèn)值:


運(yùn)行結(jié)果為:

但是要注意:

  • 如果使用常規(guī)的調(diào)用語(yǔ)法時(shí)阔馋,必須按照函數(shù)聲明中定義的參數(shù)順序來(lái)給定參數(shù)玛荞,可以省略的只有排在末尾的參數(shù)。
  • 如果使用命名參數(shù)呕寝,可以省略中間的一些參數(shù)勋眯,也可以以你想要的任意順序只給定你需要的參數(shù),例如我們只修改前綴和后綴壁涎,分隔符仍然采用默認(rèn)值:



    運(yùn)行結(jié)果為:


3.3 頂層函數(shù)和屬性

Java中凡恍,所有的代碼都需要寫(xiě)作類的函數(shù),但是在項(xiàng)目中怔球,很多代碼并不能歸屬到類中嚼酝,這時(shí)候我們一般會(huì)定義一個(gè)xxUtils類,并在其中聲明static的靜態(tài)方法竟坛。

kotlin中闽巩,我們可以把這些函數(shù)直接放到代碼文件的頂層,不用從屬于任何的類担汤,這些放在文件頂層的函數(shù)仍然是包內(nèi)的成員涎跨,如果你需要從包外訪問(wèn)它,則需要import崭歧,但不再需要額外包一層隅很。

3.3.1 在 Java 中調(diào)用頂層函數(shù)

如果我們想要在Java中調(diào)用這些頂層函數(shù),則需要通過(guò)Kotlin根據(jù)包含函數(shù)的文件的名稱生成的類率碾,例如我們有兩個(gè)文件

  • KotlinMethod.kt
fun kotlinFunc() {}
  • JavaCallKotlin.java
public class JavaCallKotlin {
    public JavaCallKotlin() {
        KotlinMethodKt.kotlinFunc();
    }
}

前者包含一個(gè)頂層函數(shù)叔营,那么在Java中,就會(huì)根據(jù)該文件名生成一個(gè){文件名}Kt的類型所宰,再通過(guò)這個(gè)類來(lái)調(diào)用這個(gè)頂層函數(shù)绒尊。

如果不想使用默認(rèn)的類名,可以在.kt文件的開(kāi)頭加上@file:JvmName("類名")的注解仔粥。

3.3.2 在 Java 中調(diào)用頂層屬性

和函數(shù)一樣婴谱,屬性也可以放到文件的頂層。默認(rèn)情況下躯泰,頂層屬性和其他任意的屬性一樣谭羔,是通過(guò)訪問(wèn)器暴露給Java使用的(如果是val就只有一個(gè)getter,如果是var就對(duì)應(yīng)gettersetter)斟冕。如果想要把一個(gè)常量以public static final的屬性暴露給Java口糕,可以使用const來(lái)修飾它。

package com.demo.lizejun.kotlinsample.chapter1

//不可變磕蛇。
val kotlinVal = "kotlinValue"
//可變景描。
var kotlinVar = "kotlinVariable"
//常量十办。
const val kotlinConst = "kotlinConst"
//頂層函數(shù)。
fun kotlinFunc() {}

Java中超棺,分別通過(guò)以下幾種方式來(lái)訪問(wèn)或者修改這幾個(gè)頂層屬性:

package com.demo.lizejun.kotlinsample.chapter3;

import com.demo.lizejun.kotlinsample.chapter1.KotlinMethodKt;

public class JavaCallKotlin {
    public JavaCallKotlin() {
        KotlinMethodKt.kotlinFunc();
        //不可變向族。
        KotlinMethodKt.getKotlinVal();
        //可變。
        KotlinMethodKt.setKotlinVar("newKotlinVar");
        KotlinMethodKt.getKotlinVar();
        //常量棠绘。
        String kotlinConst = KotlinMethodKt.kotlinConst;
    }
}

四件相、擴(kuò)展函數(shù)和屬性

擴(kuò)展函數(shù) 其實(shí)是一個(gè)類的成員函數(shù),只不過(guò)它定義在類的外面氧苍,我們所需要做的夜矗,就是在聲明擴(kuò)展函數(shù)的時(shí)候,把需要擴(kuò)展的類或者接口的名稱让虐,放到它的前面紊撕,用來(lái)調(diào)用這個(gè)擴(kuò)展函數(shù)的對(duì)象,就叫做 接收者對(duì)象赡突。

在擴(kuò)展函數(shù)中对扶,可以直接訪問(wèn)被擴(kuò)展的類的其它方法和屬性,就好像是在這個(gè)類自己的方法中訪問(wèn)它們的一樣惭缰,但是擴(kuò)展函數(shù)不允許你打破它的封裝性浪南,擴(kuò)展函數(shù)不能訪問(wèn)私有的或者是受保護(hù)的成員。

4.1 擴(kuò)展函數(shù)的定義和使用

下面我們給String類添加一個(gè)擴(kuò)展函數(shù)漱受,返回它的最后一個(gè)字符:


運(yùn)行結(jié)果為:

4.2 在 Java 中使用擴(kuò)展函數(shù)

如果需要在Java中調(diào)用擴(kuò)展函數(shù)络凿,那么把接收者對(duì)象作為第一個(gè)參數(shù)傳進(jìn)去即可:

//接收者對(duì)象作為第一個(gè)參數(shù)。
char lastChar = KotlinMethodKt.last("Kotlin");

4.3 不能重寫(xiě)的擴(kuò)展函數(shù)

這里假設(shè)我們有兩個(gè)類昂羡,ViewButton喷众,其中Button繼承于View,我們給這兩個(gè)類都添加一個(gè)名為showOff的擴(kuò)展函數(shù)紧憾。


運(yùn)行結(jié)果為:

盡管實(shí)際上這個(gè)變量是一個(gè)Button的對(duì)象,但是Kotlin會(huì)把擴(kuò)展函數(shù)當(dāng)做靜態(tài)函數(shù)來(lái)對(duì)待昌渤,因此 擴(kuò)展函數(shù)不存在重寫(xiě)赴穗。

4.4 擴(kuò)展屬性

擴(kuò)展屬性提供了一種方法,用來(lái)擴(kuò)展類的API膀息,可以用來(lái)訪問(wèn)屬性般眉,用的是屬性語(yǔ)法而不是函數(shù)的語(yǔ)法,盡管他們被稱為屬性潜支,但它們沒(méi)有任何狀態(tài)甸赃,因?yàn)闆](méi)有合適的地方來(lái)存儲(chǔ)它們。

現(xiàn)在冗酿,我們給StringBuilder添加一個(gè)可讀寫(xiě)的屬性lastChar埠对,用于獲取或者改變它的最后一個(gè)字符络断,包含以下幾點(diǎn)要素:

  • 擴(kuò)展屬性以var/val關(guān)鍵字開(kāi)頭
  • 指定擴(kuò)展屬性的名字、類型
  • 如果是var那么提供get()/set(value : T)方法项玛,而如果是val屬性貌笨,那么提供get()方法,其中T為屬性的類型襟沮。

運(yùn)行結(jié)果為:


五锥惋、可變參數(shù)、中綴調(diào)用和庫(kù)的支持

5.1 可變參數(shù)

使用關(guān)鍵字 vararg开伏,可以用來(lái)聲明一個(gè)函數(shù)將有可能有任意數(shù)量的參數(shù)膀跌,下面例子中,我們定義一個(gè)可以接收可變數(shù)量Int類型的函數(shù)固灵,之后和在Java中一樣捅伤,它會(huì)被轉(zhuǎn)換為[I的整型數(shù)組類型:


運(yùn)行結(jié)果為:

而如果我們已經(jīng)將參數(shù)打包成一個(gè)數(shù)組,這時(shí)候如果想要將它傳遞給一個(gè)接收可變參數(shù)的函數(shù)怎虫,那么需要先通過(guò)*操作符進(jìn)行解包:

運(yùn)行結(jié)果為:

5.2 中綴調(diào)用

中綴調(diào)用 不是特殊的內(nèi)置結(jié)構(gòu)暑认,而是一種特殊的函數(shù)調(diào)用。在中綴調(diào)用中大审,沒(méi)有添加額外的分隔符蘸际,函數(shù)名稱是直接放在目標(biāo)對(duì)象名稱和參數(shù)之間。例如我們聲明了一個(gè)to函數(shù)徒扶。

//一般函數(shù)調(diào)用粮彤。
1.to("One")
//中綴調(diào)用。
1 to "One"

中綴調(diào)用可以與 只有一個(gè)參數(shù)的函數(shù) 一起使用姜骡,無(wú)論是普通的函數(shù)還是擴(kuò)展函數(shù)导坟,要允許使用中綴符號(hào)調(diào)用函數(shù),需要使用infix修飾符來(lái)標(biāo)記它圈澈,下面是一個(gè)創(chuàng)建Person的函數(shù)惫周,我們采用了擴(kuò)展函數(shù)的方法,這里的AnyKotlin中所有類的父類康栈,和Java中的Object相同:


運(yùn)行的結(jié)果為:

六递递、字符串處理

6.1 分割字符串

Java中,我們會(huì)使用split來(lái)分割字符串啥么,它接受一個(gè)正則表達(dá)式作為參數(shù)登舞。但是當(dāng)我們想分割"."時(shí),會(huì)得到一個(gè)空的數(shù)組悬荣,因?yàn)?code>.號(hào)表示任何字符的正則表達(dá)式菠秒。
而在kotlin中,它提供了一個(gè)接受Regex類型的重載函數(shù)氯迂,這樣確保了當(dāng)有一個(gè)字符串傳遞給這些函數(shù)的時(shí)候践叠,不會(huì)被當(dāng)做正則表達(dá)式言缤,我們可以使用擴(kuò)展函數(shù)toRegex將字符串轉(zhuǎn)換為正則表達(dá)式。


運(yùn)行結(jié)果為:

6.2 正則表達(dá)式

假設(shè)有下面這個(gè)字符串

/Users/yole/kotlin-book/chapter.adoc

我們需要通過(guò)這個(gè)字符串獲取到chapter.adoc的目錄酵熙、文件名和擴(kuò)展名轧简,如果使用擴(kuò)展函數(shù),那么代碼如下:


運(yùn)行結(jié)果為:

下面是使用正則表達(dá)式的做法:

這個(gè)正則表達(dá)式將一個(gè)路徑分為三個(gè)由斜線和點(diǎn)分隔的組:

  • .模式從字符串的一開(kāi)始就進(jìn)行匹配匾二,所以第一組(.+)包含最后一個(gè)斜線之前的子串哮独,這和子串包含所有前面的斜線,因?yàn)樗鼈兤ヅ洹比魏巫址暗哪J健?/li>
  • 第二組包含最后一個(gè)點(diǎn)之前的子串
  • 第三組包含剩余部分

七察藐、局部函數(shù)

Java的一個(gè)函數(shù)當(dāng)中皮璧,有可能存在重復(fù)代碼,例如在注冊(cè)模塊中分飞,可能需要校驗(yàn)輸入的多個(gè)字段是否有效悴务,那么校驗(yàn)的邏輯就可以提取出一個(gè)函數(shù),而Kotlin就提供了一種方法:可以在函數(shù)中嵌套這些提取的函數(shù)譬猫,局部函數(shù)定義方式和普通函數(shù)是相同的讯檐。


運(yùn)行的結(jié)果為:


更多文章,歡迎訪問(wèn)我的 Android 知識(shí)梳理系列:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末染服,一起剝皮案震驚了整個(gè)濱河市别洪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌柳刮,老刑警劉巖挖垛,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異秉颗,居然都是意外死亡痢毒,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)蚕甥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)哪替,“玉大人,你說(shuō)我怎么就攤上這事菇怀∫募遥” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵敏释,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我摸袁,道長(zhǎng)钥顽,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任靠汁,我火速辦了婚禮蜂大,結(jié)果婚禮上闽铐,老公的妹妹穿的比我還像新娘。我一直安慰自己奶浦,他們只是感情好兄墅,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著澳叉,像睡著了一般隙咸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上成洗,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天五督,我揣著相機(jī)與錄音,去河邊找鬼瓶殃。 笑死充包,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的遥椿。 我是一名探鬼主播基矮,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼冠场!你這毒婦竟也來(lái)了家浇?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤慈鸠,失蹤者是張志新(化名)和其女友劉穎蓝谨,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體青团,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡譬巫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了督笆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芦昔。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖娃肿,靈堂內(nèi)的尸體忽然破棺而出咕缎,到底是詐尸還是另有隱情,我是刑警寧澤料扰,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布凭豪,位于F島的核電站,受9級(jí)特大地震影響晒杈,放射性物質(zhì)發(fā)生泄漏嫂伞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望帖努。 院中可真熱鬧撰豺,春花似錦、人聲如沸拼余。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)匙监。三九已至凡橱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間舅柜,已是汗流浹背梭纹。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留致份,地道東北人变抽。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像氮块,于是被迫代替她去往敵國(guó)和親绍载。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

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