一晰绎、高階函數(shù)介紹
在
Kotlin
中,高階函數(shù)即指:將函數(shù)用作一個(gè)函數(shù)的參數(shù)或者返回值的函數(shù)。
1.1风罩、將函數(shù)用作函數(shù)參數(shù)的情況的高階函數(shù)
這里介紹字符串中的sumBy{}
高階函數(shù)。先看一看源碼
// sumBy函數(shù)的源碼
public inline fun CharSequence.sumBy(selector: (Char) -> Int): Int {
var sum: Int = 0
for (element in this) {
sum += selector(element)
}
return sum
}
源碼說明:
- 大家這里可以不必糾結(jié)
inline
舵稠,和sumBy
函數(shù)前面的CharSequence.
超升。因?yàn)檫@是Koltin
中的內(nèi)聯(lián)函數(shù)
與擴(kuò)展功能
。在后面的章節(jié)中會(huì)給大家講解到的哺徊。這里主要分析高階函數(shù)室琢,故而這里不多做分析。 - 該函數(shù)返回一個(gè)
Int
類型的值落追。并且接受了一個(gè)selector()
函數(shù)作為該函數(shù)的參數(shù)盈滴。其中,selector()
函數(shù)接受一個(gè)Char
類型的參數(shù)轿钠,并且返回一個(gè)Int
類型的值巢钓。 - 定義一個(gè)
sum
變量,并且循環(huán)這個(gè)字符串疗垛,循環(huán)一次調(diào)用一次selector()
函數(shù)并加上sum
症汹。用作累加。其中this
關(guān)鍵字代表字符串本身继谚。
所以這個(gè)函數(shù)的作用是:把字符串中的每一個(gè)字符轉(zhuǎn)換為Int
的值烈菌,用于累加阵幸,最后返回累加的值
例:
val testStr = "abc"
val sum = testStr.sumBy { it.toInt() }
println(sum)
輸出結(jié)果為:
294 // 因?yàn)樽址鸻對(duì)應(yīng)的值為97,b對(duì)應(yīng)98,c對(duì)應(yīng)99芽世,故而該值即為 97 + 98 + 99 = 294
1.2挚赊、將函數(shù)用作一個(gè)函數(shù)的返回值的高階函數(shù)。
這里使用官網(wǎng)上的一個(gè)例子來講解济瓢。lock()
函數(shù)荠割,先看一看他的源碼實(shí)現(xiàn)
fun <T> lock(lock: Lock, body: () -> T): T {
lock.lock()
try {
return body()
}
finally {
lock.unlock()
}
}
源碼說明:
- 這其中用到了
kotlin
中泛型
的知識(shí)點(diǎn),這里贊不考慮旺矾。我會(huì)在后續(xù)的文章為大家講解蔑鹦。 - 從源碼可以看出,該函數(shù)接受一個(gè)
Lock
類型的變量作為參數(shù)1
箕宙,并且接受一個(gè)無參且返回類型為T
的函數(shù)作為參數(shù)2
. - 該函數(shù)的返回值為一個(gè)函數(shù)嚎朽,我們可以看這一句代碼
return body()
可以看出。
例:使用lock
函數(shù)柬帕,下面的代碼都是偽代碼哟忍,我就是按照官網(wǎng)的例子直接拿過來用的
fun toBeSynchronized() = sharedResource.operation()
val result = lock(lock, ::toBeSynchronized)
其中,::toBeSynchronized
即為對(duì)函數(shù)toBeSynchronized()
的引用陷寝,其中關(guān)于雙冒號(hào)::
的使用在這里不做討論與講解锅很。
上面的寫法也可以寫作:
val result = lock(lock, {sharedResource.operation()} )
1.3、高階函數(shù)的使用
在上面的兩個(gè)例子中凤跑,我們出現(xiàn)了str.sumBy{ it.toInt }
這樣的寫法爆安。其實(shí)這樣的寫法在前一章節(jié)Lambda使用
中已經(jīng)講解過了。這里主要講高階函數(shù)中對(duì)Lambda語法
的簡(jiǎn)寫仔引。
從上面的例子我們的寫法應(yīng)該是這樣的:
str.sumBy( { it.toInt } )
但是根據(jù)Kotlin
中的約定扔仓,即當(dāng)函數(shù)中只有一個(gè)函數(shù)作為參數(shù),并且您使用了lambda
表達(dá)式作為相應(yīng)的參數(shù)咖耘,則可以省略函數(shù)的小括號(hào)()
当辐。故而我們可以寫成:
str.sumBy{ it.toInt }
還有一個(gè)約定,即當(dāng)函數(shù)的最后一個(gè)參數(shù)是一個(gè)函數(shù)鲤看,并且你傳遞一個(gè)lambda
表達(dá)式作為相應(yīng)的參數(shù),則可以在圓括號(hào)之外指定它耍群。故而上面例2
中的代碼我們可寫成:
val result = lock(lock){
sharedResource.operation()
}
二义桂、自定義高階函數(shù)
// 源代碼
fun test(a : Int , b : Int) : Int{
return a + b
}
fun sum(num1 : Int , num2 : Int) : Int{
return num1 + num2
}
// 調(diào)用
test(10,sum(3,5)) // 結(jié)果為:18
// lambda
fun test(a : Int , b : (num1 : Int , num2 : Int) -> Int) : Int{
return a + b.invoke(3,5)
}
// 調(diào)用
test(10,{ num1: Int, num2: Int -> num1 + num2 }) // 結(jié)果為:18
可以看出上面的代碼中,直接在我的方法體中寫死了數(shù)值蹈垢,這在開發(fā)中是很不合理的慷吊,并且也不會(huì)這么寫。上面的例子只是在闡述Lambda
的語法曹抬。接下來我另舉一個(gè)例子:
例:傳入兩個(gè)參數(shù)溉瓶,并傳入一個(gè)函數(shù)來實(shí)現(xiàn)他們不同的邏輯
例:
private fun resultByOpt(num1 : Int , num2 : Int , result : (Int ,Int) -> Int) : Int{
return result(num1,num2)
}
private fun testDemo() {
val result1 = resultByOpt(1,2){
num1, num2 -> num1 + num2
}
val result2 = resultByOpt(3,4){
num1, num2 -> num1 - num2
}
val result3 = resultByOpt(5,6){
num1, num2 -> num1 * num2
}
val result4 = resultByOpt(6,3){
num1, num2 -> num1 / num2
}
println("result1 = $result1")
println("result2 = $result2")
println("result3 = $result3")
println("result4 = $result4")
}
輸出結(jié)果為:
result1 = 3
result2 = -1
result3 = 30
result4 = 2
這個(gè)例子是根據(jù)傳入不同的Lambda
表達(dá)式,實(shí)現(xiàn)了兩個(gè)數(shù)的+、-堰酿、*疾宏、/
。
當(dāng)然了触创,在實(shí)際的項(xiàng)目開發(fā)中坎藐,自己去定義高階函數(shù)的實(shí)現(xiàn)是很少了,因?yàn)橛孟到y(tǒng)給我們提供的高階函數(shù)已經(jīng)夠用了哼绑。不過岩馍,當(dāng)我們掌握了Lambda
語法以及怎么去定義高階函數(shù)的用法后。在實(shí)際開發(fā)中有了這種需求的時(shí)候也難不倒我們了抖韩。
三蛀恩、常用的標(biāo)準(zhǔn)高階函數(shù)介紹
下面介紹幾個(gè)Kotlin
中常用的標(biāo)準(zhǔn)高階函數(shù)。熟練的用好下面的幾個(gè)函數(shù)茂浮,能減少很多的代碼量双谆,并增加代碼的可讀性。下面的幾個(gè)高階函數(shù)的源碼幾乎上都出自Standard.kt
文件
3.1励稳、TODO函數(shù)
這個(gè)函數(shù)不是一個(gè)高階函數(shù)佃乘,它只是一個(gè)拋出異常以及測(cè)試錯(cuò)誤的一個(gè)普通函數(shù)。
此函數(shù)的作用:顯示拋出
NotImplementedError
錯(cuò)誤驹尼。NotImplementedError
錯(cuò)誤類繼承至Java
中的Error
趣避。我們看一看他的源碼就知道了:
public class NotImplementedError(message: String = "An operation is not implemented.") : Error(message)
TODO
函數(shù)的源碼
@kotlin.internal.InlineOnly
public inline fun TODO(): Nothing = throw NotImplementedError()
@kotlin.internal.InlineOnly
public inline fun TODO(reason: String): Nothing =
throw NotImplementedError("An operation is not implemented: $reason")
舉例說明:
fun main(args: Array<String>) {
TODO("測(cè)試TODO函數(shù),是否顯示拋出錯(cuò)誤")
}
輸出結(jié)果為:
如果調(diào)用TODO()
時(shí)新翎,不傳參數(shù)的程帕,則會(huì)輸出An operation is not implemented.
3.2 、run()函數(shù)
run
函數(shù)這里分為兩種情況講解地啰,因?yàn)樵谠创a中也分為兩個(gè)函數(shù)來實(shí)現(xiàn)的愁拭。采用不同的run
函數(shù)會(huì)有不同的效果。
3.2.1亏吝、run()
我們看下其源碼:
public inline fun <R> run(block: () -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
關(guān)于contract
這部分代碼小生也不是很懂其意思岭埠。在一些大牛的blog
上說是其編輯器對(duì)上下文的推斷。但是我也不知道對(duì)不對(duì)蔚鸥,因?yàn)樵诠倬W(wǎng)中惜论,對(duì)這個(gè)東西也沒有講解到。不過這個(gè)單詞的意思是契約止喷,合同
等等意思馆类。我想應(yīng)該和這個(gè)有關(guān)。在這里我就不做深究了弹谁。主要講講run{}
函數(shù)的用法其含義乾巧。
這里我們只關(guān)心return block()
這行代碼句喜。從源碼中我們可以看出,run
函數(shù)僅僅是執(zhí)行了我們的block()
沟于,即一個(gè)Lambda
表達(dá)式咳胃,而后返回了執(zhí)行的結(jié)果。
用法1:
當(dāng)我們需要執(zhí)行一個(gè)
代碼塊
的時(shí)候就可以用到這個(gè)函數(shù),并且這個(gè)代碼塊是獨(dú)立的社裆。即我可以在run()
函數(shù)中寫一些和項(xiàng)目無關(guān)的代碼拙绊,因?yàn)樗粫?huì)影響項(xiàng)目的正常運(yùn)行。
例: 在一個(gè)函數(shù)中使用
private fun testRun1() {
val str = "kotlin"
run{
val str = "java" // 和上面的變量不會(huì)沖突
println("str = $str")
}
println("str = $str")
}
輸出結(jié)果:
str = java
str = kotlin
用法2:
因?yàn)?code>run函數(shù)執(zhí)行了我傳進(jìn)去的
lambda
表達(dá)式并返回了執(zhí)行的結(jié)果泳秀,所以當(dāng)一個(gè)業(yè)務(wù)邏輯都需要執(zhí)行同一段代碼而根據(jù)不同的條件去判斷得到不同結(jié)果的時(shí)候标沪。可以用到run
函數(shù)
例:都要獲取字符串的長(zhǎng)度嗜傅。
val index = 3
val num = run {
when(index){
0 -> "kotlin"
1 -> "java"
2 -> "php"
3 -> "javaScript"
else -> "none"
}
}.length
println("num = $num")
輸出結(jié)果為:
num = 10
當(dāng)然這個(gè)例子沒什么實(shí)際的意義金句。
3.2.2、T.run()
其實(shí)T.run()
函數(shù)和run()
函數(shù)差不多吕嘀,關(guān)于這兩者之間的差別我們看看其源碼實(shí)現(xiàn)就明白了:
public inline fun <T, R> T.run(block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
從源碼中我們可以看出违寞,block()
這個(gè)函數(shù)參數(shù)是一個(gè)擴(kuò)展在T
類型下的函數(shù)。這說明我的block()
函數(shù)可以可以使用當(dāng)前對(duì)象的上下文偶房。所以當(dāng)我們傳入的lambda
表達(dá)式想要使用當(dāng)前對(duì)象的上下文的時(shí)候趁曼,我們可以使用這個(gè)函數(shù)。
用法:
這里就不能像上面
run()
函數(shù)那樣當(dāng)做單獨(dú)的一個(gè)代碼塊
來使用棕洋。
例:
val str = "kotlin"
str.run {
println( "length = ${this.length}" )
println( "first = ${first()}")
println( "last = ${last()}" )
}
輸出結(jié)果為:
length = 6
first = k
last = n
在其中挡闰,可以使用this
關(guān)鍵字,因?yàn)樵谶@里它就代碼str
這個(gè)對(duì)象掰盘,也可以省略摄悯。因?yàn)樵谠创a中我們就可以看出,block
()
就是一個(gè)T
類型的擴(kuò)展函數(shù)愧捕。
這在實(shí)際的開發(fā)當(dāng)中我們可以這樣用:
例: 為TextView
設(shè)置屬性奢驯。
val mTvBtn = findViewById<TextView>(R.id.text)
mTvBtn.run{
text = "kotlin"
textSize = 13f
...
}
3.3 、with()函數(shù)
其實(shí)with()
函數(shù)和T.run()
函數(shù)的作用是相同的次绘,我們這里看下其實(shí)現(xiàn)源碼:
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return receiver.block()
}
這里我們可以看出和T.run()
函數(shù)的源代碼實(shí)現(xiàn)沒有太大的差別瘪阁。故而這兩個(gè)函數(shù)的區(qū)別在于:
with
是正常的高階函數(shù),T.run()
是擴(kuò)展的高階函數(shù)邮偎。with
函數(shù)的返回值指定了receiver
為接收者罗洗。
故而上面的T.run()
函數(shù)的列子我也可用with
來實(shí)現(xiàn)相同的效果:
例:
val str = "kotlin"
with(str) {
println( "length = ${this.length}" )
println( "first = ${first()}")
println( "last = ${last()}" )
}
輸出結(jié)果為:
length = 6
first = k
last = n
為TextView
設(shè)置屬性,也可以用它來實(shí)現(xiàn)钢猛。這里我就不舉例了。
在上面舉例的時(shí)候轩缤,都是正常的列子命迈,這里舉一個(gè)特例:當(dāng)我的對(duì)象可為null
的時(shí)候贩绕,看兩個(gè)函數(shù)之間的便利性。
例:
val newStr : String? = "kotlin"
with(newStr){
println( "length = ${this?.length}" )
println( "first = ${this?.first()}")
println( "last = ${this?.last()}" )
}
newStr?.run {
println( "length = $length" )
println( "first = ${first()}")
println( "last = ${last()}" )
}
從上面的代碼我們就可以看出壶愤,當(dāng)我們使用對(duì)象可為null
時(shí)淑倾,使用T.run()
比使用with()
函數(shù)從代碼的可讀性與簡(jiǎn)潔性來說要好一些。當(dāng)然關(guān)于怎樣去選擇使用這兩個(gè)函數(shù)征椒,就得根據(jù)實(shí)際的需求以及自己的喜好了娇哆。
3.4、T.apply()函數(shù)
我們先看下T.apply()
函數(shù)的源碼:
public inline fun <T> T.apply(block: T.() -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
return this
}
從T.apply()
源碼中在結(jié)合前面提到的T.run()
函數(shù)的源碼我們可以得出,這兩個(gè)函數(shù)的邏輯差不多勃救,唯一的區(qū)別是T,apply
執(zhí)行完了block()
函數(shù)后碍讨,返回了自身對(duì)象。而T.run
是返回了執(zhí)行的結(jié)果蒙秒。
故而: T.apply
的作用除了實(shí)現(xiàn)能實(shí)現(xiàn)T.run
函數(shù)的作用外勃黍,還可以后續(xù)的再對(duì)此操作。下面我們看一個(gè)例子:
例:為TextView
設(shè)置屬性后晕讲,再設(shè)置點(diǎn)擊事件等
val mTvBtn = findViewById<TextView>(R.id.text)
mTvBtn.apply{
text = "kotlin"
textSize = 13f
...
}.apply{
// 這里可以繼續(xù)去設(shè)置屬性或一些TextView的其他一些操作
}.apply{
setOnClickListener{ .... }
}
或者:設(shè)置為Fragment
設(shè)置數(shù)據(jù)傳遞
// 原始方法
fun newInstance(id : Int , name : String , age : Int) : MimeFragment{
val fragment = MimeFragment()
fragment.arguments.putInt("id",id)
fragment.arguments.putString("name",name)
fragment.arguments.putInt("age",age)
return fragment
}
// 改進(jìn)方法
fun newInstance(id : Int , name : String , age : Int) = MimeFragment().apply {
arguments.putInt("id",id)
arguments.putString("name",name)
arguments.putInt("age",age)
}
3.5覆获、T.also()函數(shù)
關(guān)于T.also
函數(shù)來說,它和T.apply
很相似瓢省,弄息。我們先看看其源碼的實(shí)現(xiàn):
public inline fun <T> T.also(block: (T) -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block(this)
return this
}
從上面的源碼在結(jié)合T.apply
函數(shù)的源碼我們可以看出: T.also
函數(shù)中的參數(shù)block
函數(shù)傳入了自身對(duì)象。故而這個(gè)函數(shù)的作用是用用block
函數(shù)調(diào)用自身對(duì)象勤婚,最后在返回自身對(duì)象
這里舉例一個(gè)簡(jiǎn)單的例子摹量,并用實(shí)例說明其和T.apply
的區(qū)別
例:
"kotlin".also {
println("結(jié)果:${it.plus("-java")}")
}.also {
println("結(jié)果:${it.plus("-php")}")
}
"kotlin".apply {
println("結(jié)果:${this.plus("-java")}")
}.apply {
println("結(jié)果:${this.plus("-php")}")
}
他們的輸出結(jié)果是相同的:
結(jié)果:kotlin-java
結(jié)果:kotlin-php
結(jié)果:kotlin-java
結(jié)果:kotlin-php
從上面的實(shí)例我們可以看出,他們的區(qū)別在于蛔六,T.also
中只能使用it
調(diào)用自身,而T.apply
中只能使用this
調(diào)用自身荆永。因?yàn)樵谠创a中T.also
是執(zhí)行block(this)
后在返回自身。而T.apply
是執(zhí)行block()
后在返回自身国章。這就是為什么在一些函數(shù)中可以使用it
,而一些函數(shù)中只能使用this
的關(guān)鍵所在
3.6具钥、T.let()函數(shù)
在前面講解空安全、可空屬性
章節(jié)中液兽,我們講解到可以使用T.let()
函數(shù)來規(guī)避空指針的問題骂删。有興趣的朋友可以去看看我的Kotlin——初級(jí)篇(六):空類型、空安全四啰、非空斷言宁玫、類型轉(zhuǎn)換等特性總結(jié)這篇文章。但是在這篇文章中柑晒,我們只講到了它的使用欧瘪。故而今天來說一下他的源碼實(shí)現(xiàn):
public inline fun <T, R> T.let(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
}
從上面的源碼中我們可以得出,它其實(shí)和T.also
以及T.apply
都很相似匙赞。而T.let
的作用也不僅僅在使用空安全
這一個(gè)點(diǎn)上佛掖。用T.let
也可實(shí)現(xiàn)其他操作
例:
"kotlin".let {
println("原字符串:$it") // kotlin
it.reversed()
}.let {
println("反轉(zhuǎn)字符串后的值:$it") // niltok
it.plus("-java")
}.let {
println("新的字符串:$it") // niltok-java
}
"kotlin".also {
println("原字符串:$it") // kotlin
it.reversed()
}.also {
println("反轉(zhuǎn)字符串后的值:$it") // kotlin
it.plus("-java")
}.also {
println("新的字符串:$it") // kotlin
}
"kotlin".apply {
println("原字符串:$this") // kotlin
this.reversed()
}.apply {
println("反轉(zhuǎn)字符串后的值:$this") // kotlin
this.plus("-java")
}.apply {
println("新的字符串:$this") // kotlin
}
輸出結(jié)果看是否和注釋的結(jié)果一樣呢:
原字符串:kotlin
反轉(zhuǎn)字符串后的值:niltok
新的字符串:niltok-java
原字符串:kotlin
反轉(zhuǎn)字符串后的值:kotlin
新的字符串:kotlin
原字符串:kotlin
反轉(zhuǎn)字符串后的值:kotlin
新的字符串:kotlin
3.7辕翰、T.takeIf()函數(shù)
從函數(shù)的名字我們可以看出许溅,這是一個(gè)關(guān)于條件判斷
的函數(shù),我們?cè)诳雌湓创a實(shí)現(xiàn):
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
contract {
callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
}
return if (predicate(this)) this else null
}
從源碼中我們可以得出這個(gè)函數(shù)的作用是:
傳入一個(gè)你希望的一個(gè)條件损敷,如果對(duì)象符合你的條件則返回自身辽俗,反之,則返回
null
拴魄。
例: 判斷一個(gè)字符串是否由某一個(gè)字符起始冗茸,若條件成立則返回自身,反之匹中,則返回null
val str = "kotlin"
val result = str.takeIf {
it.startsWith("ko")
}
println("result = $result")
輸出結(jié)果為:
result = kotlin
3.8夏漱、T.takeUnless()函數(shù)
這個(gè)函數(shù)的作用和T.takeIf()
函數(shù)的作用是一樣的。只是和其的邏輯是相反的职员。即:傳入一個(gè)你希望的一個(gè)條件麻蹋,如果對(duì)象符合你的條件則返回null
,反之焊切,則返回自身扮授。
這里看一看它的源碼就明白了。
public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? {
contract {
callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
}
return if (!predicate(this)) this else null
}
這里就舉和T.takeIf()
函數(shù)中一樣的例子专肪,看他的結(jié)果和T.takeIf()
中的結(jié)果是不是相反的刹勃。
例:
val str = "kotlin"
val result = str.takeUnless {
it.startsWith("ko")
}
println("result = $result")
輸出結(jié)果為:
result = null
3.8、repeat()函數(shù)
首先嚎尤,我們從這個(gè)函數(shù)名就可以看出是關(guān)于重復(fù)
相關(guān)的一個(gè)函數(shù)荔仁,再看起源碼,從源碼的實(shí)現(xiàn)來說明這個(gè)函數(shù)的作用:
public inline fun repeat(times: Int, action: (Int) -> Unit) {
contract { callsInPlace(action) }
for (index in 0..times - 1) {
action(index)
}
}
從上面的代碼我們可以看出這個(gè)函數(shù)的作用是:
根據(jù)傳入的重復(fù)次數(shù)去重復(fù)執(zhí)行一個(gè)我們想要的動(dòng)作(函數(shù))
例:
repeat(5){
println("我是重復(fù)的第${it + 1}次芽死,我的索引為:$it")
}
輸出結(jié)果為:
我是重復(fù)的第1次乏梁,我的索引為:0
我是重復(fù)的第2次,我的索引為:1
我是重復(fù)的第3次关贵,我的索引為:2
我是重復(fù)的第4次遇骑,我的索引為:3
我是重復(fù)的第5次,我的索引為:4
3.9揖曾、lazy()函數(shù)
關(guān)于Lazy()
函數(shù)來說落萎,它共實(shí)現(xiàn)了4
個(gè)重載函數(shù),都是用于延遲操作炭剪,不過這里不多做介紹练链。因?yàn)樵趯?shí)際的項(xiàng)目開發(fā)中常用都是用于延遲初始化屬性。
四奴拦、對(duì)標(biāo)準(zhǔn)的高階函數(shù)總結(jié)
關(guān)于重復(fù)使用同一個(gè)函數(shù)的情況一般都只有T.also
媒鼓、T.let
、T.apply
這三個(gè)函數(shù)。而這個(gè)三個(gè)函數(shù)在上面講解這些函數(shù)的時(shí)候都用實(shí)例講解了他們的區(qū)別绿鸣。故而這里不做詳細(xì)實(shí)例介紹瓷产。并且連貫著使用這些高階函數(shù)去處理一定的邏輯,在實(shí)際項(xiàng)目中很少會(huì)這樣做枚驻。一般都是單獨(dú)使用一個(gè),或者兩個(gè)株旷、三個(gè)這個(gè)連貫這用再登。
關(guān)于他們之間的區(qū)別,以及他們用于實(shí)際項(xiàng)目中在一定的需求下到底該怎樣去選擇哪一個(gè)函數(shù)進(jìn)行使用希望大家詳細(xì)的看下他們的源碼并且根據(jù)我前面說寫的實(shí)例進(jìn)行分析晾剖。
大家也可以參考這篇文章:
掌握Kotlin標(biāo)準(zhǔn)函數(shù):run, with, let, also and apply