Kotlin中,理解T.()->Unit 、 ()->Unit與(T) -> Unit

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代表的對象

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容