天天看點

Kotlin學習筆記十六、《Kotlin學習筆記六、函數運用》的補充:擴充方法

我們知道,在Java裡面,沒有擴充方法這個概念,隻有utils工具類,我們需要實作Java本身沒有提供的功能API的時候,我們就隻有自己寫工具類來實作。

但kotlin裡面。我們是可以基于系統提供的API對系統功能進行擴充。當然這樣的擴充隻對本工程有效。

擴充方法的實作形式:正常書寫的方法名前加上“receiver”,也就是“要判斷的對象的類名.”。

比如下面的示例,我們要判斷某個String字元串的是否為空:String.isEmpty(msg:String)。其中,“String.”就是我們“要判斷的對象的類名.”,“isEmpty”就是方法名:

fun String.isEmptyOrNull(): Boolean {
    return this.isNullOrEmpty() || this.trim().isEmpty()
}
           

使用的時候很簡單,我們直接這樣調用即可:

println("${"sdfghj".isEmptyOrNull()}")
           

運作結果如下:

Kotlin學習筆記十六、《Kotlin學習筆記六、函數運用》的補充:擴充方法

再來看看一個字元串填充的擴充類:

fun String.margin(start: Int = 1, end: Int = 5, char: Char = '*', separator: CharSequence = ","): String {
//這裡的(start .. end)形成一個從start到end的前後閉合的一個閉區間;
//(start .. end).joinToString(separator):表示在這個閉合區間内,循環産生對象,每隔對象之間被separator隔開;
//而這個對象則由後面的“{}”大括弧裡面的内容指定,具體見下面大括弧裡面的注釋說明:
val padding = (start..end).joinToString(separator) {
//        //這裡的it就表示在(start .. end)閉區間内循環産生的每個對象,比如閉區間為(1 .. 5),那麼循環産生的每隔對象分别為1、2、3、4、5
//        it.toString()
//        //在(start .. end)閉區間内循環産生的每個對象由外界指定,比如這裡指定為char,預設為“*”
        char.toString()
//        //在(start .. end)閉區間内循環産生的每個對象為調用該方法的字元串本身,比如外界調用該方法的字元串為"abc",那麼産生的字元串即為“abc”
//        this
    }
   
    return "${padding}${this}${padding}"
}
           

注意事項以及含義解說,注釋裡面寫得很清楚,這裡就不再多說。

假設字元串"abc"以如下方式調用:“966487”.margin(5, 10, separator = “”),那麼上面的padding變量對應的字元串分别為:

1、it.toString()---->>>56789109664875678910
    2、char.toString()---->>>******966487******
    3、this---->>>966487966487966487966487966487966487966487966487966487966487966487966487966487
           

使用的時候調用方式如下:

println("966487".margin(5, 10, separator = ""))
           

是以擴充方法還是比較簡單。我們現在再來說對自定義的某個類擴充屬性property,直接上代碼:

自定義的類:

class PoorGuy : Guy{
    var mWealth:Double = 0.0
}
           

按慣例,我們先擴充一個方法:

對于PoorGuy這個類,我們可以為他定義擴充方法,在實作上,跟我們前面的擴充String.kt的方法沒有差別;

fun PoorGuy.noMoney() {
    println("I'm very very poor, I haven't any money to life")
}
           

我們還可以對PoorGuy這個類擴充屬性property:

1、由于在kotlin裡面,屬性property <==>java裡面的backing field + get + set,但是自定義的擴充屬性是沒有feilding存在的,是以我們不能用feilding來接收set方法裡面的參數;

2、但是我們有曲折的實作方式:我們可以在PoorGuy裡面建立一個public變量,用它來接受和傳回變量值;

3、但是要注意我們建立的這個變量必須是public的,否則無法擷取到。

var PoorGuy.wealth: Double
    get() {
        return mWealth
    }
    set(value) {
        mWealth = value
    }
           

除了擴充屬性裡面沒有field之外,interface接口也是沒有的:

1、我們知道kotlin裡面,接口内部也是可以定義自有的屬性property和具體方法實作的。

2、當我們定義屬性property時,需要注意:接口 也是沒有field的,是以他的get/set方法并沒有太多的實際意義。

3、因為get得到的是一個具體的固定值,沒法修改;有因為接口不存在field狀态,導緻不能通過field來存儲set方法的值value。

4、另外,定義的get/set方法并不能被複寫。

interface Guy{
    var guyWealth:Double
        get() {
            return 0.0
        }
        set(value) {
            當我們像下面這樣寫set方法的時候,IDE就會報錯,提示:Property in an interface cannot have a backing field
//            field = value
        }
}