Kotlin by

kotlin 中的委托模式依靠by關(guān)鍵字,語(yǔ)法定義

val/var <Property name>?:<Type>by? <expression>

var/val:屬性類型(可變/只讀)

name:屬性名稱

Type:屬性的數(shù)據(jù)類型

expression:代理類

使用場(chǎng)景:

A.延遲加載屬性(lazy property): 屬性值只在初次訪問(wèn)時(shí)才會(huì)計(jì)算,

B.可觀察屬性(observable property): 屬性發(fā)生變化時(shí), 可以向監(jiān)聽(tīng)器發(fā)送通知,

C.將多個(gè)屬性保存在一個(gè) map 內(nèi), 而不是保存在多個(gè)獨(dú)立的域內(nèi).

---------------------------------------------------------------------------------------------------------------------

A.延遲加載(Lazy)

lazy()是一個(gè)函數(shù), 接受一個(gè)Lambda表達(dá)式作為參數(shù), 返回一個(gè)Lazy類型的實(shí)例,這個(gè)實(shí)例可以作為一個(gè)委托, 實(shí)現(xiàn)延遲加載屬性(lazy property): 第一次調(diào)用 get() 時(shí), 將會(huì)執(zhí)行 lazy() 函數(shù)受到的Lambda 表達(dá)式,然后會(huì)記住這次執(zhí)行的結(jié)果, 以后所有對(duì) get() 的調(diào)用都只會(huì)簡(jiǎn)單地返回以前記住的結(jié)果.

val no: Int by lazy {

? ? 200

}

val c = 200

fun main(args: Array) {

? ? val b = 200

? ? println(no) // Log : 200

? ? println(no) // Log : 200

}

注意:

1.var類型屬性不能設(shè)置為延遲加載屬性,因?yàn)樵趌azy中并沒(méi)有setValue(…)方法

2.lazy操作符是線程安全的。如果在不考慮多線程問(wèn)題或者想提高更多的性能,也可以使?

用 lazy(LazyThreadSafeMode.NONE){ … } 。

在LazyThreadSafetyMode中聲明了幾種,[Lazy]實(shí)例在多個(gè)線程之間同步訪問(wèn)的形式:

SYNCHRONIZED:鎖定,用于確保只有一個(gè)線程可以初始化[Lazy]實(shí)例。

PUBLICATION:初始化函數(shù)可以在并發(fā)訪問(wèn)未初始化的[Lazy]實(shí)例值時(shí)調(diào)用幾次,,但只有第一個(gè)返回的值將被用作[Lazy]實(shí)例的值。

NONE:沒(méi)有鎖用于同步對(duì)[Lazy]實(shí)例值的訪問(wèn); 如果從多個(gè)線程訪問(wèn)實(shí)例,是線程不安全的。此模式應(yīng)僅在高性能至關(guān)重要,并且[Lazy]實(shí)例被保證永遠(yuǎn)不會(huì)從多個(gè)線程初始化時(shí)使用。

B1.可觀察屬性(Observable)

Delegates.observable() 函數(shù)接受兩個(gè)參數(shù): 第一個(gè)是初始化值, 第二個(gè)是屬性值變化事件的響應(yīng)器(handler).這種形式的委托,采用了觀察者模式,其會(huì)檢測(cè)可觀察屬性的變化,當(dāng)被觀察屬性的setter()方法被調(diào)用的時(shí)候,響應(yīng)器(handler)都會(huì)被調(diào)用(在屬性賦值處理完成之后)并自動(dòng)執(zhí)行執(zhí)行的lambda表達(dá)式,同時(shí)響應(yīng)器會(huì)收到三個(gè)參數(shù):被賦值的屬性, 賦值前的舊屬性值, 以及賦值后的新屬性值。

var name: String by Delegates.observable("wang", {

? ? kProperty, oldName, newName ->

? ? println("kProperty:${kProperty.name} | oldName:$oldName | newName:$newName")

})

fun main(args: Array) {

? ? println("name: $name") // Log:nam:wang

? ? name = "zhang" // Log:kProperty:name | oldName:wang | newName:zhang

? ? name = "li" // Log:kProperty:name | oldName:zhang | newName:li

}

在這個(gè)例子中,Delegates.observable(wang, hanler),完成了兩項(xiàng)工作,一是,將name初始化(name=wang);二是檢測(cè)name屬性值的變化,每次變化時(shí),都會(huì)打印其賦值前的舊屬性值, 以及賦值后的新屬性值。

B2.Vetoable

Delegates.vetoable()函數(shù)接受兩個(gè)參數(shù): 第一個(gè)是初始化值, 第二個(gè)是屬性值變化事件的響應(yīng)器(handler),是可觀察屬性(Observable)的一個(gè)特例,不同的是在響應(yīng)器指定的自動(dòng)執(zhí)行執(zhí)行的lambda表達(dá)式中在保存新值之前做一些條件判斷,來(lái)決定是否將新值保存。

var name: String by Delegates.vetoable("wang", {

? ? kProperty, oldValue, newValue ->

? ? println("oldValue:$oldValue | newValue:$newValue")

? ? newValue.contains("wang")

})

fun main(args: Array) {

? ? println("name: $name")

? ? println("------------------")

? ? name = "zhangLing"

? ? println("name: $name")

? ? println("------------------")

? ? name = "wangBing"

? ? println("name: $name")

}

//Log

name: wang

------------------

oldValue:wang | newValue:zhangLing

name: wang

------------------

oldValue:wang | newValue:wangBing

name: wangBing

代碼示例中的委托,在給name賦值是,只有字符串中含有”wang”時(shí),將新值賦值給name.第一次給name賦值“zhangLing”時(shí),lambda表達(dá)式的返回值為false,此時(shí)并沒(méi)有對(duì)name成功賦值。而第二次,賦值”wangBing” 時(shí),lambda表達(dá)式的返回值為true,成功賦值。

B3.Not Null

在實(shí)際開(kāi)發(fā)時(shí),我們可能會(huì)設(shè)置可為null的var類型屬性,在我們使用它時(shí),肯定是對(duì)其賦值,假如不賦值,必然要報(bào)NullPointException.一種解決方案是,我們可以在使用它時(shí),在每個(gè)地方不管是不是null,都做null檢查,這樣我們就保證了在使用它時(shí),保證它不是null。這樣無(wú)形當(dāng)中添加了很多重復(fù)的代碼。

在Kotlin中,委托又幫我們做了一個(gè)善事,不用去寫這些重復(fù)的代碼,Not Null委托會(huì)含有一個(gè)可null的變量并會(huì)在我們?cè)O(shè)置這個(gè)屬性的時(shí)候分配一個(gè)真實(shí)的值。如果這個(gè)值在被獲取之前沒(méi)有被分配,它就會(huì)拋出一個(gè)異常。

class App : Application() {

? ? companion object {

? ? ? ? var instance: App by Delegates.notNull()

? ? }

? ? override fun onCreate() {

? ? ? ? super.onCreate()

? ? ? ? instance = this

? ? }

}

c.將多個(gè)屬性保存在一個(gè)map內(nèi)

使用Gson解析Json時(shí),可以獲取到相應(yīng)的實(shí)體類的實(shí)例,當(dāng)然該實(shí)體類的屬性名稱與Json中的key是一一對(duì)應(yīng)的。在Kotlin中,存在這么一種委托方式,類的構(gòu)造器接受一個(gè)map實(shí)例作為參數(shù),將map實(shí)例本身作為屬性的委托,屬性的名稱與map中的key是一致的,也就是意味著我們可以很簡(jiǎn)單的從一個(gè)動(dòng)態(tài)地map中創(chuàng)建一個(gè)對(duì)象實(shí)例。

Class1.

class User(val map: Map) {

? ? val name: String by map

? ? val age: Int by map

}

Class2.

fun main(args: Array) {

? ? val user = User(mapOf(

? ? ? ? ? ? "name" to "John Doe",

? ? ? ? ? ? "age" to 25

? ? ))

? ? println(user.name) // 打印結(jié)果為: "John Doe"

? ? println(user.age) // 打印結(jié)果為: 25

}

委托屬性將從這個(gè) map中讀取屬性值(使用屬性名稱字符串作為 key 值)。

如果不用只讀的 Map , 而改用值可變的 MutableMap , 那么也可以用作 var 屬性的委托。

class User(val map: MutableMap) {

? ? val name: String by map

? ? val age: Int by map

}

fun main(args: Array) {

? ? var map:MutableMap = mutableMapOf(

? ? ? ? ? ? "name" to "John Doe",

? ? ? ? ? ? "age" to 25)

? ? val user = User(map)

? ? println(user.name) // 打印結(jié)果為: "John Doe"

? ? println(user.age) // 打印結(jié)果為: 25

? ? println("--------------")

? ? map.put("name", "Green Dao")

? ? map.put("age", 30)

? ? println(user.name) // 打印結(jié)果為: Green Dao

? ? println(user.age) // 打印結(jié)果為: 30

}

?著作權(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)容

  • Scala與Java的關(guān)系 Scala與Java的關(guān)系是非常緊密的??! 因?yàn)镾cala是基于Java虛擬機(jī),也就是...
    燈火gg閱讀 3,606評(píng)論 1 24
  • 本文是在學(xué)習(xí)和使用kotlin時(shí)的一些總結(jié)與體會(huì),一些代碼示例來(lái)自于網(wǎng)絡(luò)或Kotlin官方文檔,持續(xù)更新... 對(duì)...
    竹塵居士閱讀 3,461評(píng)論 0 8
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 34,633評(píng)論 18 399
  • 我是一個(gè)唯物主義的無(wú)神論者,記事起所受的教育,形成一種難以剔除的執(zhí)拗,我對(duì)它也毫無(wú)辦法。所以即使曾經(jīng)對(duì)佛教和基督教...
    花下鋤月閱讀 487評(píng)論 0 1
  • 文/咔芒 我看到新聞的的時(shí)候,一直以為劉鑫,是殺人兇手,看到最后,才知道,受害者是江歌,殺人兇手是陳世峰,而劉鑫呢...
    咔芒閱讀 320評(píng)論 0 0

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