Koltin中的代理屬性 - 標(biāo)準(zhǔn)委托

前言

Kotlin是一種在Java虛擬機(jī)上運(yùn)行的靜態(tài)類型編程語(yǔ)言,被稱之為Android世界的Swift,在GoogleI/O2017中,Google宣布Kotlin成為Android官方開(kāi)發(fā)語(yǔ)言

代理屬性

Kotlin中的代理屬性又被稱為屬性委托,屬性的操作就是set/get函數(shù)的調(diào)用,委托屬性會(huì)用自己的setValue/getValue去大理源屬性的實(shí)現(xiàn),委托類需要根據(jù)屬性的可變類型,實(shí)現(xiàn)對(duì)應(yīng)的setValue/getValue方法

屬性委托的語(yǔ)法:
val/var <屬性名>:屬性類型 by <表達(dá)式>

標(biāo)準(zhǔn)委托

Kotlin所提供的一些用于代理屬性的工廠方法

延遲屬性
使用lazy實(shí)現(xiàn)延遲屬性的委托,只在第一次首次訪問(wèn)的時(shí)候會(huì)計(jì)算

Kotlin中的lateinit、lazy關(guān)鍵字

可觀察屬性
每當(dāng)我們給屬性賦值的時(shí)候,就會(huì)在賦值后調(diào)用表達(dá)式中代碼塊,用于監(jiān)聽(tīng)屬性內(nèi)容的變更

var value:String by Delegates.observable("initValue"){
        pro,old,new ->
    Log.e("mike","----$pro----$old----$new")
}
value = "aaa"
value = "aaa"
value = "bbb"
//打印結(jié)果
----var com.mike.loginmvvm.login.ui.LoginActivity.value: kotlin.String----initValue----aaa
----var com.mike.loginmvvm.login.ui.LoginActivity.value: kotlin.String----aaa----aaa
----var com.mike.loginmvvm.login.ui.LoginActivity.value: kotlin.String----aaa----bbb

非空屬性代理

var data:String by Delegates.notNull()
Log.e("mike","----$data----")
//打印結(jié)果
Caused by: java.lang.IllegalStateException: Property data should be initialized before get.

查看它的源碼發(fā)現(xiàn),如果數(shù)據(jù)為空的時(shí)候會(huì)拋出異常

public override fun getValue(thisRef: Any?, property: KProperty<*>): T {
    return value ?: throw IllegalStateException("Property ${property.name} should be initialized before get.")
}

那么它和lateinit很相似,都是可以繞過(guò)編譯器檢查,都是初始化前直接使用會(huì)有異常拋出,就使用而言notNull可以用于基本數(shù)據(jù)類型,但lateinit只能用于引用數(shù)據(jù)類型

lateinit會(huì)生成這樣的代碼,這樣也能看出之所以lateinit不支持基本數(shù)據(jù)類型,也是因?yàn)榛緮?shù)據(jù)類型在java中存在默認(rèn)值的,所以不存在稍后初始化這種情況

lateinit var data:String
//java代碼
public String data;
public void get(){
    if (data == null){
        Intrinsics.throwUninitializedPropertyAccessException("data");
    }
    return data;
}

看下相同情況下的Delegates.notNull(),會(huì)產(chǎn)生一個(gè)包裝類的對(duì)象將數(shù)據(jù)進(jìn)行包裝

var value by Delegates.notNull<String>()

//會(huì)生成這樣的偽代碼
public NotNullVar value$delegate = new NotNullVar()
public String getValue(){
    return value$delegate.getValue();
}

所以當(dāng)我們?cè)谶x擇Delegates.notNull()lateinit的時(shí)候,如果是引用類型的需要延遲初始化的情況下推薦使用lateinit,開(kāi)銷相對(duì)較小,如果是基本數(shù)據(jù)類型就使用Delegates.notNull()

屬性值攔截
Delegates.observable可以查看數(shù)據(jù)的情況,在數(shù)據(jù)變化過(guò)后進(jìn)行回調(diào),vetoable則可以在數(shù)據(jù)提交之前進(jìn)行回調(diào),從而決定是否需要此次變更,當(dāng)返回false時(shí)表示丟棄此次變更

var version: Version by Delegates.vetoable(Version(0)) { pro, old, new ->
    return@vetoable new.code > old.code
}

歡迎關(guān)注Mike的簡(jiǎn)書(shū)

Android知識(shí)整理

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

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

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