亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > 綜合 > 正文

Kotlin代理屬性--官方文檔翻譯

2024-07-21 23:03:36
字體:
來源:轉載
供稿:網友

代理屬性 Delegated Properties

一些特定的常見類型的屬性, 盡管我們可以在每次需要的時候實現他們, 但是如果我們一次把他們全部實現并放在一個庫中, 這會非常方便, 包括:

延遲屬性: 只在第一次訪問的時候計算值

廣播屬性: 當屬性的值改變時通知觀察者

將數據存儲在鍵值對中, 而不是獨立的域中.

Kotlin提供的代理屬性, 包含了這些(以及其他)例子:

class Example{

var p: String by Delegate()

}

語法是:val/var : by . 在by關鍵字后面的語句是delegate, 因為屬性的get()和set()將被代理給它的getValue()和setValue()方法.

屬性代理不需要實現任何接口, 但他們需要提供一個getValue()方法(對于var---還需要提供setValue()).

例如:

class Delegate {

operator fun getValue(thisRef: Any?, property: KProperty<*>): String {

return "$thisRef, thank you for delegating '${property.name}' to me!"

}

operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {

println("$value has been assigned to '${property.name} in $thisRef.'")

}

}

當我們從被代理給Delegate實例的p時,Delegate的getValue()方法被調用,

第一個參數是讀取p所在的對象, 第二個參數保存p自身的描述(例如: 你可以獲取它的名字). 例如:

val e = Example()

println(e.p)

打印結果:

Example@33a17727, thank you for delegating ‘p’ to me!

類似的, 當我們給p賦值時,setValue()方法被調用. 前兩個參數是相同的, 第三個參數保存被賦的新值:

e.p = "NEW"

打印結果:

NEW has been assigned to ‘p’ in Example@33a17727.

關于代理對象的需求的說明可以在[這里]找到(delegated-properties.html#property-delegate-requirements).

需要注意的是從Kotlin 1.1之前你可以在方法或代碼塊中聲明代理屬性了, 代理屬性不必聲明為類的成員,例子.

標準庫中的代理 Standard Delegates

Kotlin標準庫為一些常用的代理提供了工廠方法.

延遲屬性 Lazy

lazy()方法接收一個lamda作為參數并返回一個Lazy實例, 可以實現延遲加載:

第一次調用get()時執行傳入lazy()的lambda表達式并保存結果, 后續對get()的調用只返回保存的結果.

val lazyValue: String by lazy {

println("computed!")

"Hello"

}

fun main(args: Array) {

println(lazyValue)

println(lazyValue)

}

該例子輸出:

computed!

Hello

Hello

同步的

默認情況下, 延遲屬性的計算是(synchronized): 只有一個線程計算該值, 其他的線程都會看見相同的值. 如果此初始化的步驟不需要同步, 多個線程可以同事執行初始化, 在lazy()方法中傳入LazyThreadSafetyMode.PUBLICATION作為參數.

如果可以確保初始化過程只會在單個線程中執行, 可以用LazyThreadSafetyMode.NONE模式, 該模式不保證線程安全, 避免相關的開銷.

監控屬性 Observable

Delegates.observable()有兩個參數: 初始值和變化觀察器.

每次代理屬性被賦予值的時候都會調用觀察器(在賦值操作之后).觀察器有三個參數:屬性類型, 舊值和新值.

import kotlin.properties.Delegates

class User {

var name: String by Delegates.observable("") {

prop, old, new ->

println("$old -> $new")

}

}

fun main(args: Array) {

val user = User()

user.name = "first"

user.name = "second"

}

該例子輸出

-> first

first -> second

如果你想終端賦值的過程并拒絕賦值, 用vetoable()替代observable().

observable()的觀察器參數是在賦值之前被調用的.

使用Mapc存儲屬性 Storing Properties in a Map

在map中存儲屬性是一種常見使用方式.

這種情形在解析JSON或者其他"動態的"事情時經常出現.

在這種情況下, 你可以使用map的實例來代理一個代理屬性.

classUser(val map: Map) {

val name: String by map

val age: Int by map

}

在這個例子中, 構造器接收一個map:

val user = User(mapOf(

"name" to "John Doe",

"age" to 25

))

代理屬性從這個map接收值(通過String類型的key --- 作為屬性的名字)

println(user.name) // Prints "John Doe"

println(user.age) // Prints 25

當使用MutableMap而不是只讀的Map時, 對var也可以使用.

classMutableUser(val map: MutableMap) {

var name: String by map

var age: Int by map

}

本地代理屬性 Local Delegated Properties (since 1.1)

你可以聲明局部變量作為代理屬性.

例如, 可以讓局部變量成為lazy屬性.

fun example(computeFoo: () -> Foo) {

val memoizedFoo by lazy(computeFoo)

if (someCondition && memoizedFoo.isValid()) {

memoizedFoo.doSomething()

}

}

memoizedFoo變量只會在第一次訪問時計算.

如果someCondition失敗了, 變量的值則完全不會進行計算.

屬性代理的需求 Property Delegate Requirements

在此我們整理一下代理對象的需求.

只讀

對于一個屬性(例如:val), 代理必須提供一個接收下列參數的getValue函數:

thisRef--- 必須是_屬性擁有者_相同類型或者是其超類(對于擴展屬性 --- 則是其所擴展的屬性)

property--- 必須是KProperty<*>類型或其超類,

這個函數必須返回和屬性相同的類型, 或者其子類.

可變

對于的屬性(比如var), 代理必須額外提供具備下列參數的setValue函數:

thisRef--- 與getValue()相同,

property--- 與getValue()相同,

new value --- 必須是與屬性或其超類相同的類型

getValue()和/或setValue()函數可以用兩種方式提供: 代理類的成員函數或者擴展函數.

后者在原有對象沒有提供這些函數時非常方便.兩種方式的函數都要使用operator關鍵字修飾.

代理類可以實現下面的接口之一, 包含operator方法的ReadOnlyProperty和ReadWriteProperty接口. 這些接口在Kotlin標準庫中聲明.

interface ReadOnlyProperty {

operator fun getValue(thisRef: R, property: KProperty<*>): T

}

interface ReadWriteProperty {

operator fun getValue(thisRef: R, property: KProperty<*>): T

operator fun setValue(thisRef: R, property: KProperty<*>, value: T)

}

翻譯規則 Translation Rules

在代理屬性的背后, Kotlin編譯器生成一個輔助屬性并代理給它. 比如, 對于屬性prop, 會生成一個prop$delegate輔助屬性, 訪問器的代碼就是簡單的代理給這個附加的屬性:

class C {

var prop: Type by MyDelegate()

}

// this code is generated by the compiler instead:

class C {

private val prop$delegate = MyDelegate()

var prop: Type

get() = prop$delegate.getValue(this, this::prop)

set(value: Type) = prop$delegate.setValue(this, this::prop, value)

}

Kotlin編譯器提供了所有prop屬性必需的信息: 第一個參數this引用指向包含它的外部類C,this::prop是prop自身的反射類型信息, 是KProperty類型.

提供代理 Providing a delegate (since 1.1)

通過定義provideDelegate操作符可以擴展創建屬性實現所代理對象的邏輯.如果by右側使用的對象定義了provideDelegate作為成員函數或者擴展函數, 這個函數會在創建屬性代理時被調用.

One of the possible use cases ofprovideDelegateis to check property consistency when the property is created, not only in its getter or setter.

provideDelegate一個可能的用法是用來在創建屬性期間檢查屬性的一致性, 而不是在getter或setter中.

比如你想在綁定前檢查屬性的名字, 可以這樣寫:

class ResourceLoader(id: ResourceID) {

operator fun provideDelegate(

thisRef: MyUI,

prop: KProperty<*>

): ReadOnlyProperty {

checkProperty(thisRef, prop.name)

// 創建代理

}

private fun checkProperty(thisRef: MyUI, name: String) { ... }

}

fun bindResource(id: ResourceID): ResourceLoader { ... }

class MyUI {

val image bybindResource(ResourceID.image_id)

val text bybindResource(ResourceID.text_id)

}

provideDelegate和getValue的參數相同:

thisRef--- 必須與屬性的擁有者或其超類類型相同(對于擴展屬性 -- 指被擴展的類)

property--- 必須是KProperty<*>類型或其超類.

TheprovideDelegatemethod is called for each property during the creation of theMyUIinstance, and it performs the necessary validation right away.

provideDelegate方法在每個MyUI實例創建期間都被調用, 并立即進行必要的檢驗.

如果沒有這種在屬性和其代理之間攔截的手段, 要明確的傳入屬性命, 這很不方便.

// 沒有"provideDelegate"的情況下檢查屬性命

class MyUI {

val image by bindResource(ResourceID.image_id, "image")

val text by bindResource(ResourceID.text_id, "text")

}

fun MyUI.bindResource(

id: ResourceID,

propertyName: String

): ReadOnlyProperty {

checkProperty(this, propertyName)

// 創建委托

}

在生成的代碼中,provideDelegate被調用, 以此來初始化輔助prop$delegate屬性. 比較聲明是val prop: Type by MyDelegate()的屬性生成的代碼和上面不提供provide Delegate函數的代碼.

class C {

var prop: Type by MyDelegate()

}

// 在提供`provideDelegate`函數時, 這些代碼由編譯器生成

class C {

// 調用"provideDelegate"函數創建額外的"delegate"屬性

private val prop$delegate = MyDelegate().provideDelegate(this, this::prop)

val prop: Type

get() = prop$delegate.getValue(this, this::prop)

}

注意provideDelegate函數只影響輔助屬性的創建, 并不影響getter和setter的生成.

本文為個人翻譯的Kotlin官方文檔, 原文連接:Delegated Properties


注:相關教程知識閱讀請移步到kotlin教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人免费在线视频网站| 国产精品视频在线观看| 日韩在线视频免费观看高清中文| 琪琪第一精品导航| 欧美寡妇偷汉性猛交| 欧美日韩电影在线观看| 亚洲成人网在线| 日本最新高清不卡中文字幕| 中文字幕久精品免费视频| 日韩欧美有码在线| 91系列在线播放| 午夜精品久久久久久久男人的天堂| 久操成人在线视频| 亚洲美女中文字幕| 亚洲国产91精品在线观看| 日韩精品免费电影| 日韩在线视频网| 91亚洲午夜在线| 成人情趣片在线观看免费| 国产99久久精品一区二区| 2019最新中文字幕| 亚洲国产天堂久久综合| 日韩欧美大尺度| 欧美尤物巨大精品爽| 国产精品99久久久久久人| 久久久久久91香蕉国产| 91精品国产91久久久久久最新| 91av在线播放视频| 97在线观看免费高清| 91亚洲国产成人久久精品网站| 在线观看中文字幕亚洲| 亚洲精品久久7777777| 国产日韩欧美另类| 9.1国产丝袜在线观看| 97视频在线免费观看| 久久久久国产一区二区三区| 青草成人免费视频| 久久久综合av| 欧美日产国产成人免费图片| 久久99国产精品自在自在app| 国产aⅴ夜夜欢一区二区三区| 日韩一区二区福利| 热久久免费视频精品| 操人视频在线观看欧美| 欧美日韩在线视频观看| 中文字幕不卡在线视频极品| 日韩成人在线电影网| 视频一区视频二区国产精品| 亚洲国产欧美一区二区三区同亚洲| 久久天天躁日日躁| 亚洲精品免费一区二区三区| 亚洲另类xxxx| 92看片淫黄大片欧美看国产片| 亚洲精品久久久一区二区三区| 国产精品免费一区豆花| 欧美俄罗斯乱妇| 久久精品视频免费播放| 亚洲国产日韩欧美综合久久| 欧美激情免费观看| 91精品视频在线看| 国产日韩精品入口| 成人黄色av免费在线观看| 日韩视频免费在线观看| 久久久久成人精品| 日韩成人在线观看| 青青青国产精品一区二区| 国产福利精品在线| 自拍偷拍亚洲区| 综合136福利视频在线| 亚洲欧美国产高清va在线播| 欧美成人中文字幕在线| 亚洲精品中文字| 69国产精品成人在线播放| 精品视频久久久久久久| 日韩欧美第一页| 欧美日韩国产丝袜另类| 在线看国产精品| 成人乱人伦精品视频在线观看| 中文字幕视频在线免费欧美日韩综合在线看| 国产亚洲精品久久久久动| 亚洲精品国产拍免费91在线| 久久琪琪电影院| 国产一区私人高清影院| 欧美裸体xxxxx| 在线观看精品自拍私拍| 欧美电影《睫毛膏》| 欧美理论电影在线播放| 搡老女人一区二区三区视频tv| 精品国产欧美一区二区三区成人| 日韩中文字幕在线观看| 亚洲最大福利网站| 日韩一区二区三区在线播放| 亚洲女在线观看| 国内免费久久久久久久久久久| 久久香蕉国产线看观看av| 亚洲欧洲视频在线| 亚洲免费视频网站| 亚洲日本中文字幕| 亚洲欧美在线一区二区| 欧美电影《睫毛膏》| 国产精品久久久久一区二区| 精品亚洲永久免费精品| 欧美日韩中文字幕在线| 亚洲综合自拍一区| 欧美理论电影在线观看| 91精品久久久久久久久| 国产精品jvid在线观看蜜臀| 久热爱精品视频线路一| 国产欧美精品va在线观看| 国产精品极品在线| 亚洲成人精品视频在线观看| 韩剧1988在线观看免费完整版| 亚洲欧美日韩国产中文专区| 亚洲va男人天堂| 亚洲电影免费观看高清完整版| 国产精品美女久久| 日韩av在线免费观看| 欧美精品在线免费观看| 疯狂欧美牲乱大交777| 日韩在线激情视频| 欧美日韩中文字幕在线视频| 久久九九国产精品怡红院| 在线精品视频视频中文字幕| 欧美另类交人妖| 国产午夜一区二区| 国产日韩欧美黄色| 亚洲xxxx做受欧美| 日韩在线视频免费观看高清中文| 亚洲国产精品成人精品| 最近2019中文字幕在线高清| 国产va免费精品高清在线| 国内免费久久久久久久久久久| 日韩视频免费看| 97久久精品人人澡人人爽缅北| 伦伦影院午夜日韩欧美限制| 精品一区二区三区四区在线| 日韩精品免费在线视频观看| 国产视频亚洲视频| 亚洲成人中文字幕| 色偷偷偷综合中文字幕;dd| 日韩资源在线观看| 日本午夜在线亚洲.国产| 久久久精品一区二区| 日韩欧美中文字幕在线观看| 中文字幕在线成人| 久久久久久69| wwwwwwww亚洲| 最新69国产成人精品视频免费| 国产福利视频一区二区| 成人a在线观看| 国产欧美精品一区二区| 亚洲一区二区三区乱码aⅴ蜜桃女| 国产亚洲人成a一在线v站| 成人亚洲激情网| 欧美一级bbbbb性bbbb喷潮片| 日韩免费av片在线观看| 日韩在线视频观看正片免费网站| 7m精品福利视频导航| 日本成人黄色片| 成人激情电影一区二区| 精品久久久久久国产| 亚洲国产精彩中文乱码av在线播放| 热久久99这里有精品| 国产成人精品免费视频|