kotlin代理模式就是这么简单(委托)

kotlin代理模式就是这么简单

我们都熟悉代理模式,就是把自己要做的事情委托给另外一个对象,这个对象就代理对象,java的代理模式包括静态代理以及动态代理,在这里就不过多赘述了,今天我们来说一说kotlin的代理。

kotlin中可以零样板代码地原生支持它,kotlin中包括,类代理,以及属性代理

类代理
interface Base {
fun print()
}

class BaseImpl(val x: Int) : Base {
    override fun print() { print(x) }
}

class Derived(b: Base) : Base by b

fun main(args: Array<String>) {
    val b = BaseImpl(10)
    Derived(b).print() // 输出 10
}
复制代码

可以看到kotlin实现类代理非常简单,通过关键字by就可以让b代理自己的方法,b将会在Derived中内部存储,并且编译器将生成转发给b的所有 Base的方法。

属性代理

谈到属性代理,我们用到的较多的有lazy、Delegates.notNull()、Delegates.observable()等,这些都是kotlin自带的一些标准代理,那我们自己来写一个属性代理

class Example {
	val p: String by Delegate()
}

class Delegate {
}
复制代码

如果我们直接这样写的话,会发现Delegate下面会有错误提示, miss 'getValue(mainActivity: MainActivity, property: KProperty<*>): Any' method on delegate of type 'Delegate' 这个提示的意思是说需要提供一个getValue的方法,如果我们把p前面改成var,那么编译器又会提示一个需要setValue方法。

class Example {
	var p: String by Delegate()
}

class Delegate {
	private var mRealValue = ""

	operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return mRealValue
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        mRealValue = value
    }
}
复制代码

其实属性的代理,就是把自己的属性对应的get()和set()会被代理给它的getValue()和setValue()方法。两函数都需要用 operator 关键字来进行标记,代理类可以实现包含所需 operator 方法的 ReadOnlyProperty 或 ReadWriteProperty 接口之一,这俩接口是在 Kotlin 标准库中声明的。

在每个代理属性的实现的背后,Kotlin 编译器都会生成辅助属性并代理给它。例如,对于属性 prop,生成隐藏属性 prop$delegate,而访问器的代码只是简单地代理给这个附加属性:

class C {
	var prop: Type by MyDelegate()
}

// 这段是由编译器生成的相应代码:
class C {
    private val prop$delegate = MyDelegate()
    var prop: Type
        get() = prop$delegate.getValue(this, this::prop)
        set(value: Type) = prop$delegate.setValue(this, this::prop, value)
}
复制代码

Kotlin 编译器在参数中提供了关于 prop 的所有必要信息:第一个参数 this 引用到外部类C的实例而this::prop是KProperty类型的反射象,该对象描述prop自身。 我们继续分析一下lazy方法,自己写一个lazy的属性

class Demo1 {
	private val a by lazy { 1 }
}
复制代码

使用kotlin bytecode工具查看字节码,再进行反编译

public final class Demo1 {
   // $FF: synthetic field
   static final KProperty[] $$delegatedProperties = new KProperty[]{(KProperty)Reflection.property1(new PropertyReference1Impl(Reflection.getOrCreateKotlinClass(Demo1.class), "a", "getA()I"))};
   private final Lazy a$delegate;

   private final int getA() {
      Lazy var1 = this.a$delegate;
      KProperty var3 = $$delegatedProperties[0];
      return ((Number)var1.getValue()).intValue();
   }

   public Demo1() {
      this.a$delegate = LazyKt.lazy((Function0)null.INSTANCE);
   }
}
复制代码

编译器为我们生成了一个a$delegate的Lazy,以及$$delegatedProperties的KProperty[]对象,还有一个getA的方法,并且在构造里面通过 LazyKt.lazy((Function0)null.INSTANCE)初始化了a$delegate,这个方法其实就是我们的lazy()方法,我们继续看lazy方法

public 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 实现代码里,通过 _value 用来真正保存属性的值。_value 的默认值是 UNINITIALIZED_VALUE (一个自定义的对象)。当 _value 不是默认值的时候,就会直接把 _value 的值作为 getValue() 的返回;当 _value 还是默认值的时候,就会调用 initializer 初始化表达式完成初始化,赋值给 _value 并作为 getValue() 的返回

所以我们再获取a的值时会去先调用getA()方法,回去调用Lazy的getValue方法,然后就会走SynchronizedLazyImpl的懒属性的逻辑,整个lazy的流程就是这样。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值