Kotlin委托的使用和原理

本文详细介绍了Kotlin中的委托概念,包括类委托(通过by关键字将方法逻辑委托给其他对象实现)、属性委托(处理get和set方法)以及延迟属性(Lazyval)和可观察属性(Observablevar)的使用和原理。
摘要由CSDN通过智能技术生成

Kotlin委托的使用和原理

什么是委托

委托就是一种通过将实际工作交给其他对象来实现的设计模式;kotlin给我们提供了by关键词实现委托.

类委托

首先来看类委托,类委托的意思就是A中持有一个B的实例,A实现某个功能都交给B来实际执行.我们来看代码:

interface IVehicle {
    fun drive():String
}
​
class Car(private val vehicle: IVehicle) : IVehicle by vehicle
​
fun main(){
    val car = Car(object :IVehicle{
        override fun drive(): String {
            return "drive car"
        }
    })
    println(car.drive())
}

Car类实现了IVehicle接口及持有了一个IVehicle实例,并通过by关键词将逻辑委托给vehicle.反编译成java代码看下:

public final class Car implements IVehicle {
   private final IVehicle vehicle;
​
   public Car(@NotNull IVehicle vehicle) {
      Intrinsics.checkNotNullParameter(vehicle, "vehicle");
      super();
      this.vehicle = vehicle;
   }
​
   @NotNull
   public String drive() {
      return this.vehicle.drive();
   }
}

Car这个类实现了IVehicle,且通过by属性委托,编译器自动生成了drive()接口方法的实现,并调用构造方法中传入的委托对象的drive()方法.

属性委托

属性委托就是指一个类实现了ReadWriteProperty接口,同时把一个属性的get和set方法委托给这个委托类.我们来看代码:

class PropertyDelegate: ReadWriteProperty<Any?, Int> {
    var v = 0
    override fun getValue(thisRef: Any?, property: KProperty<*>): Int {
        println("getValue")
        return v
    }
​
    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
        println("setValue")
        v = value * value
    }
}
​
fun main(){
    var propertyValue :Int by PropertyDelegate()
    propertyValue = 10
    println(propertyValue)
}

这段代码中首先声明了一个委托类,实现了setValue和getValue两个方法,实际上这两个方法都是运算符重载方法,以getValue为例,它其实是这个方法:

/**
 * Returns the value of the property for the given object.
 * @param thisRef the object for which the value is requested.
 * @param property the metadata for the property.
 * @return the property value.
 */
public override operator fun getValue(thisRef: T, property: KProperty<*>): V

在main方法中通过by关键字把value委托给委托类实例,只要对value赋值或获取value时,就会调用到委托类的getValue和setValue方法.

我们看下反编译后的代码:

public final class PropertyDelegate implements ReadWriteProperty {
   private int v;
​
   public final int getV() {
      return this.v;
   }
​
   public final void setV(int var1) {
      this.v = var1;
   }
​
   @NotNull
   public Integer getValue(@Nullable Object thisRef, @NotNull KProperty property) {
      Intrinsics.checkNotNullParameter(property, "property");
      String var3 = "getValue";
      System.out.println(var3);
      return this.v;
   }
​
   // $FF: synthetic method
   // $FF: bridge method
   public Object getValue(Object var1, KProperty var2) {
      return this.getValue(var1, var2);
   }
​
   public void setValue(@Nullable Object thisRef, @NotNull KProperty property, int value) {
      Intrinsics.checkNotNullParameter(property, "property");
      String var4 = "setValue";
      System.out.println(var4);
      this.v = value * value;
   }
​
   // $FF: synthetic method
   // $FF: bridge method
   public void setValue(Object var1, KProperty var2, Object var3) {
      this.setValue(var1, var2, ((Number)var3).intValue());
   }
}
​
public final class PropertyDelegateKt {
   // $FF: synthetic field
   static final KProperty[] $$delegatedProperties = new KProperty[]{(KProperty)Reflection.mutableProperty0(new MutablePropertyReference0Impl(PropertyDelegateKt.class, "propertyValue", "<v#0>", 1))};
​
   public static final void main() {
      PropertyDelegate var10000 = new PropertyDelegate();
      KProperty var1 = $$delegatedProperties[0];
      PropertyDelegate propertyValue = var10000;
      propertyValue.setValue((Object)null, var1, 10);
      int var2 = propertyValue.getValue((Object)null, var1);
      System.out.println(var2);
   }
​
   // $FF: synthetic method
   public static void main(String[] var0) {
      main();
   }
}
​
​

在main方法中,生成了一个PropertyDelegate代理类,当对propertyValue赋值时就会调用代理类的setValue方法,当获取propertyValue值的时候就调用代理类的getValue方法.

属性委托还有一种用法,看一下代码

fun main(){
    val map:MutableMap<String,String> = mutableMapOf()
    map["name"] = "name1"
​
    var name by map
    println(name)
    name = "name2"
}

当访问/修改name时,就会从map中获取key为name的value值并返回,看下反编译后的代码:

public final class MapDelegateKt {
   // $FF: synthetic field
   static final KProperty[] $$delegatedProperties = new KProperty[]{(KProperty)Reflection.mutableProperty0(new MutablePropertyReference0Impl(MapDelegateKt.class, "name", "<v#0>", 1))};
​
   public static final void main() {
      Map map = (Map)(new LinkedHashMap());
      map.put("name", "name1");
      KProperty var2 = $$delegatedProperties[0];
      Object var4 = null;
      Object var3 = MapsKt.getOrImplicitDefaultNullable(map, var2.getName());
      System.out.println(var3);
      var4 = null;
      String var5 = "name2";
      map.put(var2.getName(), var5);
   }
​
   // $FF: synthetic method
   public static void main(String[] var0) {
      main();
   }
}

  1. 通过反射生成了一个KProperty类型对象变量$$delegatedProperties,通过这个对象的getName()我们就能拿到变量名称,比如这里的"name"变量名;
  2. 最终调用了MapsKt.getOrImplicitDefaultNullable方法,去map散列表去查找"name"这个key对应的value;

Kotlin提供的属性委托

  1. 延迟属性Lazy

    val count : Int by lazy{
        println("init")
        0
    }
    
    

    lazy() 接受一个lambda表达式并返回一个Lazy实例的函数,只有当第一次调用count时,count变量才会初始化,也就是调用lambda表达式.lazy()的实现是一个SynchronizedLazyImpl()实例

    private class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable {
        private var initializer: (() -> T)? = initializer
        @Volatile private var _value: Any? = UNINITIALIZED_VALUE
        // final field is required to enable safe publication of constructed instance
        private val lock = lock ?: this
    
        override val value: T
            get() {
                val _v1 = _value
                if (_v1 !== UNINITIALIZED_VALUE) {
                    @Suppress("UNCHECKED_CAST")
                    return _v1 as T
                }
    
                return synchronized(lock) {
                    val _v2 = _value
                    if (_v2 !== UNINITIALIZED_VALUE) {
                        @Suppress("UNCHECKED_CAST") (_v2 as T)
                    } else {
                        val typedValue = initializer!!()
                        _value = typedValue
                        initializer = null
                        typedValue
                    }
                }
            }
    
        override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE
    
        override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet."
    
        private fun writeReplace(): Any = InitializedLazyImpl(value)
    }
    
    
  2. 可观察属性Observable

    var age : Int by Delegates.observable(0) {
            _, oldValue, newValue ->
        println("old value : $oldValue, new value : $newValue")
        newValue > oldValue
    }
    
    

    Delegates.observable()接受两个参数,一个是初始值,一个是修改时的lambda表达式:

    public abstract class ObservableProperty<V>(initialValue: V) : ReadWriteProperty<Any?, V> {
        private var value = initialValue
    
        /**
         *  The callback which is called before a change to the property value is attempted.
         *  The value of the property hasn't been changed yet, when this callback is invoked.
         *  If the callback returns `true` the value of the property is being set to the new value,
         *  and if the callback returns `false` the new value is discarded and the property remains its old value.
         */
        protected open fun beforeChange(property: KProperty<*>, oldValue: V, newValue: V): Boolean = true
    
        /**
         * The callback which is called after the change of the property is made. The value of the property
         * has already been changed when this callback is invoked.
         */
        protected open fun afterChange(property: KProperty<*>, oldValue: V, newValue: V): Unit {}
    
        public override fun getValue(thisRef: Any?, property: KProperty<*>): V {
            return value
        }
    
        public override fun setValue(thisRef: Any?, property: KProperty<*>, value: V) {
            val oldValue = this.value
            if (!beforeChange(property, oldValue, value)) {
                return
            }
            this.value = value
            afterChange(property, oldValue, value)
        }
    }
    
    

如果你看到了这里,觉得文章写得不错就给个赞呗?
更多Android进阶指南 ,可以扫码 解锁更多Android进阶资料

在这里插入图片描述

敲代码不易,关注一下吧。ღ( ´・ᴗ・` )

  • 27
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kotlin Flow是一种用于异步数据流处理的库,它提供了一种类似于RxJava的响应式编程模型。Flow的实现原理主要涉及以下几个方面: 1. Flow的基本概念:Flow是一种冷流(Cold Stream),它是一种异步的、可取消的序列。Flow中的数据是按需产生的,只有当有收集器订阅时,才会开始产生数据。 2. Flow的操作符:Flow提供了一系列的操作符,用于对数据流进行转换、过滤、合并等操作。这些操作符是惰性的,只有当有收集器订阅时,才会触发数据的处理。 3. Flow的调度器:Flow可以通过调度器指定数据流的执行线程。调度器可以将数据流的处理切换到指定的线程池或协程上下文中,以实现并发执行或避免阻塞主线程。 4. Flow的背压支持:Flow提供了背压支持,可以通过调整缓冲区大小或使用缓存策略来处理生产者和消费者之间的速度不匹配问题。 5. Flow的异常处理:Flow可以通过catch操作符捕获异常,并在异常发生时执行特定的逻辑。此外,Flow还提供了retry和retryWhen操作符,用于处理异常重试。 6. Flow的取消支持:Flow可以通过取消协程来终止数据流的产生和处理。当取消流时,Flow会自动取消相关的协程,以释放资源并停止数据的产生。 总结起来,Kotlin Flow的实现原理主要涉及冷流、操作符、调度器、背压支持、异常处理和取消支持等方面。通过理解这些原理,可以更好地使用和理解Kotlin Flow库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值