Kotlin 委托(2)变量委托是什么、自定义变量委托

1.委托是什么?

1.1 官网示例

  在每个变量委托的实现的背后,Kotlin 编译器都会生成辅助对象并委托给它。 假设委托如下,

 1 class C {
 2     var prop: Type by MyDelegate()
 3 }
 4 

  那么编译器生成的相应代码如下:

1 class C {
2     private val prop$delegate = MyDelegate()
3     var prop: Type
4         get() = prop$delegate.getValue(this, this::prop)
5         set(value: Type) = prop$delegate.setValue(this, this::prop, value)
6 }

  其中:

  • val prop$delegate 就是被委托的对象
  • getValue与setValue就是对prop的管理函数

1.2 变量委托是一系列类

  变量委托是重载setValue,getValue运算符的类,可直接重载或者实现ReadWriteProperty、ReadOnlyProperty 接口之一。

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

  其中

  • thisRef —— 必须与委托都类型相同或者是它的超类型;
  • property —— 必须是类型 KProperty<*> 或其超类型。
  • value 必须与委托者同类型或者是它的子类型
  • 返回值与委托者相同类型(或其子类型)

  下面看下lazy是怎么实现的

1 val i11 by lazy { 1 }

  点开lazy的实现

/**
 * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer]
 * and the default thread-safety mode [LazyThreadSafetyMode.SYNCHRONIZED].
 *
 * If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access.
 *
 * Note that the returned instance uses itself to synchronize on. Do not synchronize from external code on
 * the returned instance as it may cause accidental deadlock. Also this behavior can be changed in the future.
 */
public actual fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)

  lazy是个函数 ,返回Lazy<T> ,再看下Lazy

 1 /**
 2  * Represents a value with lazy initialization.
 3  *
 4  * To create an instance of [Lazy] use the [lazy] function.
 5  */
 6 public interface Lazy<out T> {
 7     /**
 8      * Gets the lazily initialized value of the current Lazy instance.
 9      * Once the value was initialized it must not change during the rest of lifetime of this Lazy instance.
10      */
11     public val value: T
12 
13     /**
14      * Returns `true` if a value for this Lazy instance has been already initialized, and `false` otherwise.
15      * Once this function has returned `true` it stays `true` for the rest of lifetime of this Lazy instance.
16      */
17     public fun isInitialized(): Boolean
18 }

  并没有operator getValue,往下看

1 /**
2  * An extension to delegate a read-only property of type [T] to an instance of [Lazy].
3  *
4  * This extension allows to use instances of Lazy for property delegation:
5  * `val property: String by lazy { initializer }`
6  */
7 @kotlin.internal.InlineOnly
8 public inline operator fun <T> Lazy<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value

   原来它是扩展重载的getValue运算符。

  再看下Delegates.observable,它返回的 ObservableProperty 实现了 ReadWriteProperty 接口。

 1    /**
 2      * Returns a property delegate for a read/write property that calls a specified callback function when changed.
 3      * @param initialValue the initial value of the property.
 4      * @param onChange the callback which is called after the change of the property is made. The value of the property
 5      *  has already been changed when this callback is invoked.
 6      *
 7      *  @sample samples.properties.Delegates.observableDelegate
 8      */
 9     public inline fun <T> observable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit):
10             ReadWriteProperty<Any?, T> =
11         object : ObservableProperty<T>(initialValue) {
12             override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = onChange(property, oldValue, newValue)
13         }

 

 1 public abstract class ObservableProperty<T>(initialValue: T) : ReadWriteProperty<Any?, T> {
 2     
 3     //...
 4     public override fun getValue(thisRef: Any?, property: KProperty<*>): T {
 5         return value
 6     }
 7 
 8     public override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
 9         val oldValue = this.value
10         if (!beforeChange(property, oldValue, value)) {
11             return
12         }
13         this.value = value
14         afterChange(property, oldValue, value)
15     }
16 }

2.by后面的是什么?

  by后面的是委托类的一个对象

  示例代码

 1 class lazy11(var default : Int = -1,var lmda : () -> Int) {
 2     operator fun provideDelegate( thisRef : Any,prop : KProperty<*>) : Delegate13 {
 3         return Delegate13(lmda)
 4     }
 5 }
 6 
 7 val i11 by lazy { 1 }
 8 
 9 class D11{
10     val MAX by lazy { 1024 }
11 
12     var lazy = lazy{ 9 }
13     val value : Int by lazy
14 
15     var lazy11 = lazy11{8}
16     var count : Int by lazy11
17 }
18 
19 fun delegate_test11(){
20     Log.e(TAG_DELEGATE,"====================================== delegate_test_11 ")
21 
22     var d11 = D11()
23     Log.e(TAG_DELEGATE,"d11.value = ${d11.value},d11.count = ${d11.count} ,d11.MAX = ${d11.MAX}")
24 }

  结果

2019-09-13 16:54:51.742 10374-10374/com.example.kotlin E/delegate: ====================================== delegate_test_11 
2019-09-13 16:54:51.744 10374-10374/com.example.kotlin E/delegate: Delegate13.getValue
2019-09-13 16:54:51.744 10374-10374/com.example.kotlin E/delegate: d11.value = 9,d11.count = 8 ,d11.MAX = 1024

  其中:MAX委托的是编译器生成的对象,而value与count则是直接托委的成员对象。

3.自定义变量委托

3.1 直接重载getValue,setValue运算符

 1 class BYY{
 2     var value : Int = -1
 3 
 4     operator fun setValue(thisRef: Any, property: KProperty<*>, v : Int) {
 5         Log.e(TAG_DELEGATE,"BYY.setValue")
 6         value = v
 7     }
 8     operator fun getValue(thisRef: Any, property: KProperty<*>): Int {
 9         Log.e(TAG_DELEGATE,"BYY.getValue")
10         return value
11     }
12 }
13 operator fun BYY.setValue(thisRef: Nothing?, property: KProperty<*>, v : Int){
14 
15 }
16 operator fun BYY.get(thisRef: Nothing?, property: KProperty<*>) = value
17 
18 class D12{
19     var size  : Int by BYY()
20 }
21 
22 fun delegate_test12(){
23     Log.e(TAG_DELEGATE,"====================================== delegate_test_12 ")
24     var d12 = D12()
25     d12.size = 128
26     Log.e(TAG_DELEGATE,"d12.size = ${d12.size}")
27 
28 }

  结果

2019-09-13 17:02:43.564 10695-10695/com.example.kotlin E/delegate: ====================================== delegate_test_12 
2019-09-13 17:02:43.564 10695-10695/com.example.kotlin E/delegate: BYY.setValue
2019-09-13 17:02:43.564 10695-10695/com.example.kotlin E/delegate: BYY.getValue
2019-09-13 17:02:43.564 10695-10695/com.example.kotlin E/delegate: d12.size = 128

3.2 实现 委托接口 

  ReadOnlyProperty 与 ReadWriteProperty 这两个接口声明了getValue,setValue两个运算符,

 1 class MyDelegate() : ReadOnlyProperty<DC12,Int>,ReadWriteProperty<DC12,Int>{
 2     var value : Int = 0
 3     override fun setValue(thisRef: DC12, property: KProperty<*>, v : Int) {
 4         Log.e(TAG_DELEGATE,"MyDelegate.setValue ")
 5         value = v
 6     }
 7 
 8     override fun getValue(thisRef: DC12, property: KProperty<*>) : Int {
 9         Log.e(TAG_DELEGATE,"MyDelegate.setValue ")
10         return value
11     }
12     constructor(lmda : ()-> Int) : this (){
13         value = lmda()
14     }
15 }
16 fun getNum() : Int{
17     Log.e(TAG_DELEGATE,"getNum ")
18     return 33
19 }
20 
21 class DC12{
22     var value   : Int by MyDelegate()
23     var value2  : Int by MyDelegate(::getNum)
24 }
25 
26 fun delegate_test12(){
27     Log.e(TAG_DELEGATE,"====================================== delegate_test_12 ")
28 
29     var dc12 = DC12()
30     dc12.value = 64
31     Log.e(TAG_DELEGATE,"dc12.value = ${dc12.value},dc12.value2 = ${dc12.value2}")
32 }

  结果

2019-09-13 17:04:07.213 10931-10931/com.example.kotlin E/delegate: ====================================== delegate_test_12 
2019-09-13 17:04:07.214 10931-10931/com.example.kotlin E/delegate: getNum 
2019-09-13 17:04:07.214 10931-10931/com.example.kotlin E/delegate: MyDelegate.setValue 
2019-09-13 17:04:07.214 10931-10931/com.example.kotlin E/delegate: MyDelegate.setValue 
2019-09-13 17:04:07.214 10931-10931/com.example.kotlin E/delegate: MyDelegate.setValue 
2019-09-13 17:04:07.214 10931-10931/com.example.kotlin E/delegate: dc12.value = 64,dc12.value2 = 33

3.3 委托提供运算符 provideDelegate

  如果 by 右侧所使用的对象将 provideDelegate 定义为成员或扩展函数,那么会调用该函数来创建属性委托实例。

 1 class Delegate13 (lmda: () -> Int) : ReadOnlyProperty<Any,Int>,ReadWriteProperty<Any,Int>{
 2     var COUNT : Int
 3     init{
 4         COUNT = lmda()
 5     }
 6     override fun setValue(thisRef: Any, property: KProperty<*>, value: Int) {
 7         Log.e(TAG_DELEGATE,"Delegate13.setValue")
 8         COUNT = value
 9     }
10     override fun getValue(thisRef: Any, property: KProperty<*>): Int {
11         Log.e(TAG_DELEGATE,"Delegate13.getValue")
12         return COUNT
13     }
14 }
15 class mutableLazy(var default : Int = -1,var lmda : () -> Int) {
16     operator fun provideDelegate( thisRef : Any,prop : KProperty<*>) : Delegate13 {
17         return Delegate13(lmda)
18     }
19 }
20 
21 class D13{
22     var value : Int by mutableLazy{
23         Log.e(TAG_DELEGATE,"mutableLazy.lmda")
24         99
25     }
26 }
27 
28 fun delegate_test13(){
29     Log.e(TAG_DELEGATE,"====================================== delegate_test_13 ")
30 
31     var d13 = D13()
32     Log.e(TAG_DELEGATE,"d13.value = ${d13.value}")
33 
34     d13.value = 299
35     Log.e(TAG_DELEGATE,"d13.value = ${d13.value}")
36 }

  结果 

2019-09-13 20:52:31.350 25146-25146/com.example.kotlin E/delegate: ====================================== delegate_test_13 
2019-09-13 20:52:31.350 25146-25146/com.example.kotlin E/delegate: mutableLazy.lmda
2019-09-13 20:52:31.350 25146-25146/com.example.kotlin E/delegate: Delegate13.getValue
2019-09-13 20:52:31.350 25146-25146/com.example.kotlin E/delegate: d13.value = 99
2019-09-13 20:52:31.350 25146-25146/com.example.kotlin E/delegate: Delegate13.setValue
2019-09-13 20:52:31.350 25146-25146/com.example.kotlin E/delegate: Delegate13.getValue
2019-09-13 20:52:31.351 25146-25146/com.example.kotlin E/delegate: d13.value = 299

 

posted @ 2019-09-13 16:10  f9q  阅读(514)  评论(0编辑  收藏  举报