Android Kotlin 委託(十一)

2021-09-26 05:51:31 字數 4629 閱讀 6972

六句讓我們瞬間頓悟的話

1.概念:

委託模式是軟體設計模式中的一項基本技巧。在委託模式中,有兩個物件參與處理同乙個請求,接受請求的物件將請求委託給另乙個物件來處理。

kotlin 直接支援委託模式,更加優雅,簡潔。kotlin 通過關鍵字 by 實現委託。

2. 類委託

類的委託即乙個類中定義的方法實際是呼叫另乙個類的物件的方法來實現的。

以下例項中派生類 derived 繼承了介面 base 所有方法,並且委託乙個傳入的 base 類的物件來執行這些方法。

// 建立介面

inte***ce base

// 實現此介面的被委託的類

class baseimpl(val x: int) : base

}// 通過關鍵字 by 建立委託類

class derived(b: base) : base by b

fun main(args: array)

在 derived 宣告中,by 子句表示,將 b 儲存在 derived 的物件例項內部,而且編譯器將會生成繼承自 base 介面的所有方法, 並將呼叫**給 b。

3. 屬性委託

屬性委託指的是乙個類的某個屬性值不是在類中直接進行定義,而是將其託付給乙個**類,從而實現對該類的屬性統一管理。

屬性委託語法格式:

val/var 《屬性名》: 《型別》 by 《表示式》

by 關鍵字之後的表示式就是委託, 屬性的 get() 方法(以及set() 方法)將被委託給這個物件的 getvalue() 和 setvalue() 方法。屬性委託不必實現任何介面, 但必須提供 getvalue() 函式(對於 var屬性,還需要 setvalue() 函式)。

3. 定義乙個被委託的類

該類需要包含 getvalue() 方法和 setvalue() 方法,且引數 thisref 為進行委託的類的物件,prop 為進行委託的屬性的物件。

import kotlin.reflect.kproperty

// 定義包含屬性委託的類

class example

// 委託的類

class delegate 屬性"

}operator fun setvalue(thisref: any?, property: kproperty<*>, value: string) 屬性賦值為 $value")

}}fun main(args: array)

輸出結果為:

example@433c675d, 這裡委託了 p 屬性

example@433c675d 的 p 屬性賦值為 runoob

example@433c675d, 這裡委託了 p 屬性

4. 延遲屬性 lazy

lazy() 是乙個函式, 接受乙個 lambda 表示式作為引數, 返回乙個 lazy 例項的函式,返回的例項可以作為實現延遲屬性的委託: 第一次呼叫 get() 會執行已傳遞給 lazy() 的 lamda 表示式並記錄結果, 後續呼叫 get() 只是返回記錄的結果。

val lazyvalue: string by lazy 

fun main(args: array)

執行輸出結果:

computed!

hello

hello

5. 可觀察屬性 observable

observable 可以用於實現觀察者模式。

delegates.observable() 函式接受兩個引數: 第乙個是初始化值, 第二個是屬性值變化事件的響應器(handler)。

在屬性賦值後會執行事件的響應器(handler),它有三個引數:被賦值的屬性、舊值和新值:

import kotlin.properties.delegates

class user

}fun main(args: array)

執行輸出結果:

舊值:初始值 -> 新值:第一次賦值

舊值:第一次賦值 -> 新值:第二次賦值

6. 把屬性儲存在對映中

乙個常見的用例是在乙個對映(map)裡儲存屬性的值。 這經常出現在像解析 json 或者做其他"動態"事情的應用中。 在這種情況下,你可以使用對映例項自身作為委託來實現委託屬性。

class site(val map: map) 

fun main(args: array)

執行輸出結果:

菜鳥教程

www.runoob.com

如果使用 var 屬性,需要把 map 換成 mutablemap:

class site(val map: mutablemap) 

fun main(args: array)

執行輸出結果:

菜鳥教程

www.runoob.com

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

google

www.google.com

7. not null

notnull 適用於那些無法在初始化階段就確定屬性值的場合。

class foo 

foo.notnullbar = "bar"

println(foo.notnullbar)

需要注意,如果屬性在賦值前就被訪問的話則會丟擲異常。

8. 區域性委託屬性

你可以將區域性變數宣告為委託屬性。 例如,你可以使乙個區域性變數惰性初始化:

fun example(computefoo: () -> foo) 

}

memoizedfoo 變數只會在第一次訪問時計算。

如果 somecondition 失敗,那麼該變數根本不會計算。

9. 屬性委託要求

對於唯讀屬性(也就是說val屬性), 它的委託必須提供乙個名為getvalue()的函式。該函式接受以下引數:

這個函式必須返回與屬性相同的型別(或其子型別)。

對於乙個值可變(mutable)屬性(也就是說,var 屬性),除 getvalue()函式之外,它的委託還必須 另外再提供乙個名為setvalue()的函式, 這個函式接受以下引數:

10. 翻譯規則

在每個委託屬性的實現的背後,kotlin 編譯器都會生成輔助屬性並委託給它。 例如,對於屬性 prop,生成隱藏屬性 prop$delegate,而訪問器的**只是簡單地委託給這個附加屬性:

class c 

// 這段是由編譯器生成的相應**:

class c

kotlin 編譯器在引數中提供了關於 prop 的所有必要資訊:第乙個引數 this 引用到外部類 c 的例項而 this::prop 是 kproperty 型別的反射物件,該物件描述 prop 自身。

11. 提供委託

通過定義 providedelegate 操作符,可以擴充套件建立屬性實現所委託物件的邏輯。 如果 by 右側所使用的物件將 providedelegate 定義為成員或擴充套件函式,那麼會呼叫該函式來 建立屬性委託例項。

providedelegate 的乙個可能的使用場景是在建立屬性時(而不僅在其 getter 或 setter 中)檢查屬性一致性。

例如,如果要在繫結之前檢查屬性名稱,可以這樣寫:

class resourceloader(id: resourceid) 

private fun checkproperty(thisref: myui, name: string)

}fun bindresource(id: resourceid): resourceloader

class myui

providedelegate 的引數與 getvalue 相同:

在建立 myui 例項期間,為每個屬性呼叫 providedelegate 方法,並立即執行必要的驗證。

如果沒有這種攔截屬性與其委託之間的繫結的能力,為了實現相同的功能, 你必須顯式傳遞屬性名,這不是很方便:

// 檢查屬性名稱而不使用「providedelegate」功能

class myui

fun myui.bindresource(

id: resourceid,

propertyname: string

): readonlyproperty

在生成的**中,會呼叫 providedelegate 方法來初始化輔助的 prop$delegate 屬性。 比較對於屬性宣告 val prop: type by mydelegate() 生成的**與 上面(當 providedelegate 方法不存在時)生成的**:

class c 

// 這段**是當「providedelegate」功能可用時

// 由編譯器生成的**:

class c

請注意,providedelegate 方法只影響輔助屬性的建立,並不會影響為 getter 或 setter 生成的**。

Android Kotlin問題總結

kotlin雖然已經在2017年5月18日的谷歌i o被推舉為官方開發語言,但是問題還是有的。plugin supporting feature facet kotlin language is currently disabled.可以更新kotlin外掛程式試試。unable to parse ...

Android Kotlin 開發之旅

kotlin語言推出已經兩年之久了,作為一種火熱的全棧開發語言,本人卻一直沒有正式在專案中使用,最近專案重構中需要使用kotlin語言,這篇部落格也作為乙個學習筆記。在專案的bulid.gradle 中配置 buildscript dependencies kotlin 支援擴充套件,使用kotli...

Android Kotlin 擴充套件(七)

我相信 能考第一名的那個人,一定是每一科都不會差,哪怕是政治 地理這樣的科目。而我們身邊最優秀的人,也會把每一件事都盡力做好,不管是大事還是小事,是涉及自己或是別人。1.概念 kotlin 可以對乙個類的屬性和方法進行擴充套件,且不需要繼承或使用 decorator 模式。擴充套件是一種靜態行為,對...