kotlin委托代理

QuibblerQuibbler 2023-12-13 约 8 分钟 1419 次阅读

kotlin委托代理

设计模式中有个委托模式(即代理模式),kotlin中的委托可以通过by关键字实现。

1、接口委托

如何用Kotlin实现一个接口委托呢?举个例子,有一个接口:

interface IProxy {
        fun handle()
    }

普通方式,先实现这个接口:

class ProxyImp : IProxy {
        override fun handle() {
        }
    }

在用代理类封装一下:

class ProxyBase(private val proxy: IProxy) : IProxy {
        override fun handle() {
            proxy.handle()
        }
    }

换成Kotlin,仅需一个by关键字即可:

//用该实例代理
    class ProxyBase : IProxy by ProxyImp()

    //使用传入的参数代理
    class ProxyBase(private val proxy: IProxy) : IProxy by proxy

2、属性委托

属性委托指的是一个类的某个属性值不是在类中直接进行定义,而是将其托付给一个代理类,从而实现对该类的属性统一管理。

val/var <属性名>: <类型> by <表达式>

3、延迟委托

使用by lazy延迟加载,是Kotlin提供的一种懒加载技术,代码块中的代码并不会在一开始就执行,只有在使用时才会进行初始化值,一般和依赖注入配合使用。

使用也很简单,例如字符串变量的延迟加载:

val name: String by lazy {
        "Quibbler"
    }

查看对应的Java代码如下:

@NotNull
   private static final Lazy name$delegate;
   
   @NotNull
   public static final String getName() {
      Lazy var0 = name$delegate;
      Object var1 = null;
      Object var2 = null;
      return (String)var0.getValue();
   }
   
   static {
      name$delegate = LazyKt.lazy((Function0)null.INSTANCE);
   }

从Kotlin源码角度看Lazy的实现逻辑:

public actual fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)
    
    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)
    }

从源码中不难看出原理基本逻辑:

  • 默认为SynchronizedLazyImpl实现,initializer是lambda表达式,比如最上面的Lazy的lambda为{"Quibbler"}
  • 默认值赋值为UNINITIALIZED_VALUE,如果不为默认值则直接返回,说明已经赋值过了。
  • 后面的赋值方法由Synchronized包裹,支持多线程访问,先检查是否为UNINITIALIZED_VALUE,不为默认值直接返回
  • 未赋值过,先执行initializer,返回值赋值给typedValue,同时initializer = null,然后返回结果value

相关推荐

Parcelize:Parcelable 实现生成器
Kotlin

Parcelize:Parcelable 实现生成器

Parcelize:Parcelable 实现生成器Parcelable是安卓开发中常用的序列化方式,之前分享过一个Parcelable序列化插件,方便开发者快速生成代码,提高开发效率。1、Parcelize插件Kotlin官方也推出一个Parcelable自动生成的Gradle插件:Parcelize。1.1、引入插件在项目的build.gradle中添加:id("kotlin-parceliz

2.6k
Kotlin的继承
Kotlin

Kotlin的继承

Kotlin的继承1、超类:Any类似于Java中的Object类,Kotlin也有一个叫Any的超类,是所有类的父类,所有类都默认继承自该类。超类的定义如下,其中定义了三个函数:2、open注意上面的Any类用open修饰,表示该类可以被继承。Kotlin中的类默认都是final的,无法被继承:如果想让类可以被继承,就需要用在定义类的地方用open关键字标识该类可以被继承。3、构造器继承中涉及到

2.1k
 Kotlin基本语法
Kotlin

Kotlin基本语法

Kotlin基本语法了解Kotlin语言的基本语法。1、包kotlin文件以.kt结尾,编译文件还是如此只不过在文件名后面加上Kt后缀。这一点和Java不同,Java源文件.java,编译后为.class文件。1.1、包定义每个kotlin文件的第一行就用关键字package定义该文件所在的包。例:1.2、导包用到其它kotlin文件需要使用关键字import导入,这一点和Java一样。kotli

2.1k