Kotlin比Java更方便的地方,其中之一是可以將函數(shù)作為參數(shù)捷枯。
上面三者都是將函數(shù)作為其它函數(shù)的參數(shù)來使用滚秩,其形式雖然簡單,但理解并不簡單铜靶。
一叔遂、共同點
三者的返回值相同,均為Unit争剿,即沒有返回值已艰。
當(dāng)然有返回值也可以,比如返回一個泛型R蚕苇,或者是一個具體的值Int等
如:
T.()->R哩掺、 ()->R、(T) -> R
或者:
T.()->Int涩笤、 ()->Int嚼吞、(T) -> Int
但是這不是重點,要理解三者蹬碧,主要是分析前面的部分舱禽,這里返回Unit只是為了方便理解。
二恩沽、定義形式
可以結(jié)合Kotlin自帶的作用域函數(shù)來理解:
apply:
fun T.apply(block: T.() -> Unit): T { block(); return this }
also:
fun T.also(block: (T) -> Unit): T { block(this); return this }
自定義一個使用()->Unit的例子:
inline fun <T> T.doWithTry(block: () -> Unit) {
try {
block()
} catch (e: Throwable) {
e.printStackTrace()
}
}
三誊稚、使用
//定義了一個Person類
class Person(val name:String){
var age:Int = 0
var sex:Int = 0
}
fun test() {
val person= Person("張三")
person.also {
//沒有指定參數(shù)名字,必須用it代指參數(shù)
it.age = 20 //it不能省略
it.sex = 0 //it不能省略
}
//或者
person.also {personValue->
//使用指定的參數(shù)名,同樣personValue不能省略
personValue.age = 20
personValue.sex = 0
}
person.apply {
//直接訪問Person的屬性
this.age = 20 //this可以省略
this.sex = 1 //this可以省略
}
person.doWithTry{
//只能通過外部變量來訪問Person
person.age = 20
person.sex = 1
}
}
上面的例子說明了以下幾點:
1罗心、T.()->Unit 的函數(shù)體中可以直接使用T代表的對象里伯,即用this代表對象
2、(T) -> Unit 將T表示的對象作為實參通過函數(shù)參數(shù)傳遞進(jìn)來渤闷,供函數(shù)體使用
3疾瓮、 ()->Unit與T表示的對象沒有直接聯(lián)系,只能通過外部T實例的變量來訪問對象
四飒箭、理解
T.()->Unit 中用this代表對象狼电,而this的使用一般是一個類的成員函數(shù)中用來表示該類的實例對象本身蜒灰,比如,為Person類加一個函數(shù):
class Person(val name:String){
var age:Int = 0
var sex:Int = 0
fun info(){
//此函數(shù)中用this表示了當(dāng)前的Person對象肩碟,this可以省略
println("age is ${this.age},sex is ${if(sex == 0) "女" else "男"}")
}
}
所以我們可以這樣理解卷员,T.()->Unit相當(dāng)于是給類T定義了一個擴展函數(shù),該函數(shù)沒有形參腾务,沒有返回值,當(dāng)然我們也可以增加參數(shù)與返回值削饵,道理是一樣的岩瘦。
正是因為T.()為T的擴展函數(shù),所以可以在函數(shù)體里直接訪問T對象的屬性或者成員函數(shù)窿撬。
(T) -> Unit與 ()->Unit只是一個普通的函數(shù)启昧,一個帶有參數(shù),類型為T劈伴,另一個沒有參數(shù)而已密末。
(T) -> Unit在使用it表示實參,是Lambda表達(dá)式所規(guī)定
//Lambda表達(dá)式形式
person.also {
//沒有指定參數(shù)名字,必須用it代指參數(shù)
it.age = 20 //it不能省略
it.sex = 0 //it不能省略
}
//不使用Lambda表達(dá)式的原始形式
person.also(
//定義了一個匿名函數(shù)严里,符合also的參數(shù)要求
//it為參數(shù)名,可以更改成其它任何符合要求的名稱
fun(it:Person){
//由also函數(shù)的定義可知追城,person對象會通過形參it傳給匿名函數(shù)
it.age = 20
it.sex = 0
}
)
五刹碾、總結(jié)
1座柱、()->Unit與(T) -> Unit是相同的色洞,只是一個帶參,一個不帶參
(T) -> Unit通過形參T可將對象作為實參傳給函數(shù)锦针,所以函數(shù)體里能通過it或者指定名稱的方式來訪問該對象
2伞插、T.()->Unit 等同于為T定義了一個無參數(shù)的擴展函數(shù)媚污,所以在函數(shù)體內(nèi)可以直接通過this或省略來訪問T代表的對象