Kotlin比Java更方便的地方,其中之一是可以將函數(shù)作為參數(shù)。
上面三者都是將函數(shù)作為其它函數(shù)的參數(shù)來使用,其形式雖然簡單,但理解并不簡單。
一、共同點
三者的返回值相同,均為Unit,即沒有返回值。
當然有返回值也可以,比如返回一個泛型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ù)傳遞進來,供函數(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表示了當前的Person對象,this可以省略
println("age is ${this.age},sex is ${if(sex == 0) "女" else "男"}")
}
}
所以我們可以這樣理解,T.()->Unit相當于是給類T定義了一個擴展函數(shù),該函數(shù)沒有形參,沒有返回值,當然我們也可以增加參數(shù)與返回值,道理是一樣的。
正是因為T.()為T的擴展函數(shù),所以可以在函數(shù)體里直接訪問T對象的屬性或者成員函數(shù)。
(T) -> Unit與 ()->Unit只是一個普通的函數(shù),一個帶有參數(shù),類型為T,另一個沒有參數(shù)而已。
(T) -> Unit在使用it表示實參,是Lambda表達式所規(guī)定
//Lambda表達式形式
person.also {
//沒有指定參數(shù)名字,必須用it代指參數(shù)
it.age = 20 //it不能省略
it.sex = 0 //it不能省略
}
//不使用Lambda表達式的原始形式
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代表的對象