• 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
  • 相关阅读:
    ACM-ICPC 2018 徐州赛区网络预赛 I. Characters with Hash
    hdu 5437
    poj 1502
    ACM-ICPC 2018 沈阳赛区网络预赛 K. Supreme Number
    ACM-ICPC 2018 沈阳赛区网络预赛 F. Fantastic Graph
    ACM-ICPC 2018 南京赛区网络预赛 B. The writing on the wall
    ACM-ICPC 2018 南京赛区网络预赛 J. Sum
    法里数列
    ACM-ICPC 2018 南京赛区网络预赛 L. Magical Girl Haze
    Hashtable 为什么不叫 HashTable?
  • 原文地址:https://www.cnblogs.com/mhbs/p/11517048.html
Copyright © 2020-2023  润新知