狠狠撸

狠狠撸Share a Scribd company logo
Kotlin黑魔法:Delegated Properties
En-Ping Hsieh
大綱
●什麼是 Delegated Properties?
●Built-in Delegated Properties
●自己的Delegated Properties自己做!
什麼是 Delegated Properties?
笔谤辞辫别谤迟测是什麼?
定义一个叫苍补尘别的笔谤辞辫别谤迟测
所以笔谤辞辫别谤迟测就是变数?
Field
類別的資料成員,用來保存狀態的。
Property Field不是
定义一个叫产耻濒产叠谤颈驳丑迟苍别蝉蝉的笔谤辞辫别谤迟测
Property
物件的屬性,通過存取器(Getter/Setter)來表現資料
當你定義一個 property X,編譯器會為你產生
●一組存取器(accessors):getX(), setX(...)
●Backing field
當你去讀取 property X 時
val y = this.x
實則是隱式調用getX()
val y = this.getX()
同理,當你對 property X 賦值時
this.x = y
其實是呼叫setX(...)
this.setX(y)
Properties represent
accessors(getter/setter), not field.
因為Property是由函式組成,所以代表著可以有更
多的使用可能。
例如有一个代表面积的辫谤辞辫别谤迟测
又或者是满足序列化和易用性...
但也有些需要小心的地方...
这样会造成重复定义...
或是不小心就递迴了...
或是不小心就递迴了...
回顾一下笔谤辞辫别谤迟测...
Setter
Getter
Property
Field
Other
valvar
A little more...
Kotlin黑魔法:Delegated Properties
Kotlin黑魔法:Delegated Properties
什麼是 Delegate?
假設我定義一個 CountableList 介面,除了取值和
插入外,還要能夠記錄取值的次數。
Kotlin黑魔法:Delegated Properties
繼承 ArrayList 並實作 CountableList 介面?
Kotlin黑魔法:Delegated Properties
讓我們想想這有沒有什麼缺點?
●函數名稱容易衝突,被父類別限制。
●由於是繼承,無法在執行時期變更實作。
如果把础谤谤补测尝颈蝉迟放在惭测尝颈蝉迟裡面,再把任务都交给他?
Kotlin黑魔法:Delegated Properties
這樣做改變了什麼?
●函數名稱容易衝突,被父類別限制。
●由於是繼承因此無法在執行時期變更實作。
?
?
委派模式是一種物件導向的設計模式,旨在希望透過組合而
非繼承的方式達到程式碼重用。
什麼是Delegated Properties?
開發中發現行為相似的 properties,而這時候可
以將這些行為提取成類別並使用委派來取代相似
的程式碼。
var/val by DelegateObject()prop: Type
Delegated Property的使用方式
Built-in Delegated Properties
notNull, map, lazy and observable
NotNull
lateinit不適用於基本型態,可以使用notNull。
Map
property 會被委派給 map 中同名 key 的值
Lazy
●Lazy initialization
●Thread-safe
● LazyThreadSafetyMode.SYNCHRONIZED (預設)
只初始化一次且保證執行緒安全。
● LazyThreadSafetyMode.PUBLICATION
可能會初始化多次,但只有首次的結果會被使用。
● LazyThreadSafetyMode.NONE
只有延遲初始化,適合在單一執行緒下的元件如View widget。
Lazy Delegation的執行緒安全模式
翱产蝉别谤惫补产濒别(不是搁虫那个)
自己的Delegated Properties自己做!
Show, don’t tell.
Kotlin黑魔法:Delegated Properties
Kotlin黑魔法:Delegated Properties
Delegated Properties 可以做到哪些功能?
●View and Resource Binding
取代 ButterKnife 或是不想使用 Kotlin Android Extension
●Data Binding
SharedPreference或是Configuration
●Dependency Injection
Koin中大量使用
Let’s get our hands dirty!
Kotlin黑魔法:Delegated Properties
這看起來是相似的模式,都是記錄property
的改變和讀取,且可能有許多類似的需求。
回顧一下Delegated Properties
Setter
Getter
Property
valvar
by
Delegated Object
getValue()
setValue()
field(optional)
Class Owner {
}
Delegated classProperty
定義Delegated Object的關係
var/val by DelegatedClass()prop: Type
Property type
Property owner
var by
class LogProperty
operator fun getValue()
operator fun setValue()
userId: String
profile: Profile?
var value : Generic type
設計Delegated Object
再看一次原本的程式码...
Kotlin黑魔法:Delegated Properties
希望简化后...
Kotlin黑魔法:Delegated Properties
var value
Generic type
fun getValue
log value
fun setValue
log value changed
仔細瞧瞧setValue()
●thisRef: Any?
●prop: KProperty<*>
●newValue: T
仔細瞧瞧setValue()
●thisRef: Any?
參數的型態限制delegated class可以在哪些property owner下使用。
其型態必須是property owner的型態或其父類別型態。
若property 位在top-level時會是Null
每次property被賦值時,該property owner的實例也會被當作參數傳入。
Class PropertyOwner {
}
var/val by DelegatedClass()prop: Type
仔細瞧瞧setValue()
●prop: KProperty<*>
其型態必須是KProperty<*>的型態或其父類別型態。
每次property被賦值時,該property的名稱(ex. “userId”, “profile”)和property
type(ex. String, Profile?)以及各種資訊會被封裝成KProperty型態的參數傳入
。
Class PropertyOwner {
}
var/val by DelegatedClass()prop: Type
仔細瞧瞧setValue()
●newValue: T
參數的型態限制哪些property type可以使用該delegated class。其型態必須
是該property的型態或其父類別型態。
每次property被賦值時,新的值會被作為參數傳遞。
Class PropertyOwner {
}
var/val by DelegatedClass()prop: Type
仔細瞧瞧setValue()
●函數主體
Log.d(tag, "${prop.name}: $value -> $newValue")
value = newValue
Class PropertyOwner {
}
var/val by DelegatedClass()prop: Type
但这些这些函数签名很难记得...
善用Kotlin提供的Delegated Properties 介面
●val → 實作ReadOnlyProperty<R, T>
var → 實作ReadWriteProperty<R, T>
●R 代表 property owner 而 T 代表 property type
Class PropertyOwner {
}
var/val by DelegatedClass()prop: Type
挑战时间!
Kotlin黑魔法:Delegated Properties
Kotlin黑魔法:Delegated Properties
Kotlin黑魔法:Delegated Properties
Summary
●Properties 代表存取函式而非欄位
●委派模式允許物件通過組合來達成程式碼重用
●DRY! 多用lazy, notNull
●觀察相似的部分並抽取出來成為Delegated Property
●Delegated Property可以藉由泛型功能取代Annotation processing
●預先定義的介面幫助我們更容易實作Delegated Properties
參考資料
●Effective Kotlin - Item 21
●https://hackernoon.com/kotlin-delegates-in-android-development-part-1-50346cf4aed7
●https://medium.com/techshots/delegate-properties-in-kotlin-39524fc4ea13
●https://americanexpress.io/advanced-kotlin-delegates/
●https://proandroiddev.com/the-magic-in-kotlin-delegates-377d27a7b531
●https://medium.com/rocket-fuel/kotlin-by-property-delegation-create-reusable-code-
f2bc2253e227
The End

More Related Content

Kotlin黑魔法:Delegated Properties

Editor's Notes

  • #6: 定義 name的屬性 這不就是一個變數?
  • #7: 這邊說的變數其實應該是是Field, 用來保存資料
  • #11: Getter/setter 統稱Accessors
  • #14: Property 是由functions構成的
  • #16: 面積>=0, 每次檢查很煩 通過override setter 來正規化
  • #17: epochDate其實並不存在存放變數 field,因此 當序列化時只有epochTimestamp會被序列化
  • #20: 如果不小心在getter呼叫自己 ..you might..
  • #23: Recap Property 看起來像變數但實際上代表getter/setter
  • #25: Extension Property
  • #29: 名字不好,原因待会说(父类别衝突)
  • #36: 在物件导向中,委託模式是一种很常见的模式,它使得我们可以用聚合来替代继承,既保留弹性又可以达成程式码的復用
  • #39: delegated object -> 具有一些特殊的operator fun
  • #42: 怕空值可以使用飞颈迟丑顿别蹿补耻濒迟
  • #48: Bind view or resource , replace butter knife
  • #49: Bind fragment getArguments()
  • #50: Annotation processing Replace by “delegate prop” easy, type-safe property delegation.
  • #69: 但不論有沒有implement interface都沒差 operator 的調用是在compile-time時期決定