美文网首页
Kotlin实现自定义属性对其它属性及方法的代理

Kotlin实现自定义属性对其它属性及方法的代理

作者: 狼性代码人 | 来源:发表于2021-01-07 21:38 被阅读0次
  • 核心思想
  • 饿汉式的属性代理
  • 懒汉式的属性代理
  • 示例代码

一、核心思想

  当我们对属性进行赋值时会触发属性的重载运算符函数setValue,而获取属性值时又会触发属性重载运算符函数getValue,所以只要重载定义属性的setValuegetValue方法,并在此方法中调用实际操作对象,就可以实现对其它方法及属性的代理。

二、饿汉式的属性代理

  • 应用场景:在代理此对象的时候,此对象已经被创建并能够获取到的情况。
  • 无Reciever:主要应对T()::KProperty \ T()::KFunction、以及顶级属性和方法的情况。

1、仅提供Getter代理

// 通用创建Getter代理
fun <T> delegateOf(getter: () -> T): ReadOnlyProperty<Any, T> = Delegate0GetterOf(getter)
// 属性快捷创建Getter代理
fun <T> KProperty0<T>.delegator(): ReadOnlyProperty<Any, T> = Delegate0GetterOf(this)
// 方法快捷创建Getter代理
@JvmName("delegateGetter")
fun <R> KFunction0<R>.delegator(): ReadOnlyProperty<Any, R> = Delegate0GetterOf(this)

internal class Delegate0GetterOf<T>(private val getter: () -> T) : ReadOnlyProperty<Any, T>,
    Serializable {
    constructor(property: KProperty0<T>) : this(property::get)

    override fun getValue(thisRef: Any, property: KProperty<*>): T = getter.invoke()
}

2、仅提供Setter代理

// 通用创建Setter代理
fun <T> delegateOf(
    setter: (T) -> Unit,
    initializedValue: T? = null
): WriteOnlyProperty<T> = Delegate0SetterOf(setter, initializedValue)
// 方法快捷创建Setter代理
@JvmName("delegateSetter")
fun <T> KFunction1<T, Unit>.delegator(initializedValue: T? = null): WriteOnlyProperty<T> =
    Delegate0SetterOf(this, initializedValue)

abstract class WriteOnlyProperty<V> : ReadWriteProperty<Any, V> {
    final override fun getValue(thisRef: Any, property: KProperty<*>): V =
        throw NoSuchMethodException("The value of ${property.name} can't be get!")
}

internal class Delegate0SetterOf<T>(
    private val setter: (T) -> Unit,
    initializedValue: T? = null
) : WriteOnlyProperty<T>(), Serializable {
    constructor(property: KMutableProperty0<T>, initializedValue: T? = null)
            : this(property::set, initializedValue)

    init {
        initializedValue?.also { setter.invoke(it) }
    }

    override fun setValue(thisRef: Any, property: KProperty<*>, value: T) = setter.invoke(value)
}

3、仅提供Getter、Setter代理

// 通用创建Getter、Setter代理
fun <T> delegateOf(
    getter: () -> T,
    setter: (T) -> Unit,
    initializedValue: T? = null
): ReadWriteProperty<Any, T> = Delegate0Of(getter, setter, initializedValue)
// 属性快捷创建Getter、Setter代理
fun <T> KMutableProperty0<T>.delegator(initializedValue: T? = null): ReadWriteProperty<Any, T> =
    Delegate0Of(this, initializedValue)

internal class Delegate0Of<T>(
    private val getter: () -> T,
    private val setter: (T) -> Unit,
    initializedValue: T? = null
) : ReadWriteProperty<Any, T>, Serializable {
    constructor(property: KMutableProperty0<T>, initializedValue: T? = null)
            : this(property::get, property::set, initializedValue)

    init {
        initializedValue?.also { setter.invoke(it) }
    }

    override fun getValue(thisRef: Any, property: KProperty<*>): T = getter.invoke()
    override fun setValue(thisRef: Any, property: KProperty<*>, value: T) = setter.invoke(value)
}

  • 有Reciever:主要应对T::KProperty \ T::KFunction的情况。

1、仅提供Getter代理

// 通用创建Getter代理
fun <T, R> delegateOf(receiver: R, getter: (R) -> T): ReadOnlyProperty<Any, T> =
    DelegateGetterOf(receiver, getter)
// 属性快捷创建Getter代理
fun <T, R> KProperty1<R, T>.delegator(receiver: R): ReadOnlyProperty<Any, T> =
    DelegateGetterOf(receiver, this)
// 方法快捷创建Getter代理
@JvmName("delegateGetter")
fun <T, R> KFunction1<R, T>.delegator(receiver: R): ReadOnlyProperty<Any, T> =
    DelegateGetterOf(receiver, this)

internal class DelegateGetterOf<T, R>(override val receiver: R, getter: (R) -> T) :
    AbsObjectGetterPropertyDelegate1<R, T>(getter) {
    constructor(receiver: R, property: KProperty1<R, T>) : this(receiver, property::get)
}

internal abstract class AbsObjectGetterPropertyDelegate1<R, T>(
    private val getter: (R) -> T
) : ReadOnlyProperty<Any, T>, Serializable {
    protected abstract val receiver: R
    final override fun getValue(thisRef: Any, property: KProperty<*>): T = getter.invoke(receiver)
}

2、仅提供Setter代理

// 通用创建Setter代理
fun <T, R> delegateOf(
    receiver: R,
    setter: (R, T) -> Unit,
    initializedValue: T? = null
): WriteOnlyProperty<T> = DelegateSetterOf(receiver, setter, initializedValue)
// 方法快捷创建Setter代理
@JvmName("delegateSetter")
fun <R, T> KFunction2<R, T, Unit>.delegator(receiver: R, initializedValue: T? = null)
        : WriteOnlyProperty<T> = DelegateSetterOf(receiver, this, initializedValue)

internal class DelegateSetterOf<T, R>(
    override val receiver: R,
    setter: (R, T) -> Unit,
    initializedValue: T? = null
) : AbsObjectSetterPropertyDelegate1<R, T>(setter) {
    constructor(receiver: R, property: KMutableProperty1<R, T>, initializedValue: T? = null)
            : this(receiver, property::set, initializedValue)

    init {
        initializedValue?.also { setter.invoke(receiver, it) }
    }
}

internal abstract class AbsObjectSetterPropertyDelegate1<R, T>(
    private val setter: (R, T) -> Unit
) : WriteOnlyProperty<T>(), Serializable {
    protected abstract val receiver: R
    override fun setValue(thisRef: Any, property: KProperty<*>, value: T) =
        setter.invoke(receiver, value)
}

3、仅提供Getter、Setter代理

// 通用创建Getter、Setter代理
fun <T, R> delegateOf(
    receiver: R,
    getter: (R) -> T,
    setter: (R, T) -> Unit,
    initializedValue: T? = null
): ReadWriteProperty<Any, T> = DelegateOf(receiver, getter, setter, initializedValue)
// 属性快捷创建Getter、Setter代理
fun <T, R> KMutableProperty1<R, T>.delegator(
    receiver: R,
    initializedValue: T? = null
): ReadWriteProperty<Any, T> = DelegateOf(receiver, this, initializedValue)

internal class DelegateOf<T, R>(
    override val receiver: R,
    getter: (R) -> T,
    setter: (R, T) -> Unit,
    initializedValue: T? = null
) : AbsObjectPropertyDelegate1<R, T>(getter, setter) {
    constructor(receiver: R, property: KMutableProperty1<R, T>, initializedValue: T? = null)
            : this(receiver, property::get, property::set, initializedValue)

    init {
        initializedValue?.also { setter.invoke(receiver, it) }
    }
}

internal abstract class AbsObjectPropertyDelegate1<R, T>(
    private val getter: (R) -> T,
    private val setter: (R, T) -> Unit
) : ReadWriteProperty<Any, T>, Serializable {
    protected abstract val receiver: R
    final override fun getValue(thisRef: Any, property: KProperty<*>): T = getter.invoke(receiver)
    final override operator fun setValue(thisRef: Any, property: KProperty<*>, value: T) =
        setter.invoke(receiver, value)
}

三、懒汉式的属性代理

  • 应用场景:在代理此对象的时候,此对象未被创建 或 创建了暂时获取不到的情况。
// 如android中这种情况
val name by delegateLazyOf(TextView::getText, TextView::setText) {
    findViewById<TextView>(R.id.textview)
}
private val listener: (Button, View.OnClickListener) -> Unit = Button::setOnClickListener
var continuationListener by delegateLazyOf(listener) {
    findViewById<Button>(R.id.continuation)
}
  • Reciever需要懒加载:主要应对T::KProperty \ T::KFunction,并且reciever在调用时才加载的情况。

1、仅提供Getter代理

// 通用创建Getter代理
fun <T, R> delegateLazyOf(getter: (R) -> T, lazyReceiver: () -> R): ReadOnlyProperty<Any, T> =
    DelegateGetterLazyOf(lazyReceiver, getter)
// 属性快捷创建Getter代理
fun <T, R> KProperty1<R, T>.delegatorLazy(lazyReceiver: () -> R): ReadOnlyProperty<Any, T> =
    DelegateGetterLazyOf(lazyReceiver, this)
// 方法快捷创建Getter代理
@JvmName("delegateGetterLazy")
fun <T, R> KFunction1<R, T>.delegatorLazy(lazyReceiver: () -> R): ReadOnlyProperty<Any, T> =
    DelegateGetterLazyOf(lazyReceiver, this)

internal class DelegateGetterLazyOf<T, R>(
    lazyReceiver: () -> R,
    getter: (R) -> T
) : AbsObjectGetterPropertyDelegate1<R, T>(getter) {
    constructor(lazyReceiver: () -> R, property: KProperty1<R, T>)
            : this(lazyReceiver, property::get)

    override val receiver: R by lazy { lazyReceiver() }
}

internal abstract class AbsObjectGetterPropertyDelegate1<R, T>(
    private val getter: (R) -> T
) : ReadOnlyProperty<Any, T>, Serializable {
    protected abstract val receiver: R
    final override fun getValue(thisRef: Any, property: KProperty<*>): T = getter.invoke(receiver)
}

2、仅提供Setter代理

// 通用创建Setter代理
fun <T, R> delegateLazyOf(
    setter: (R, T) -> Unit,
    initializedValue: T? = null,
    lazyReceiver: () -> R
): WriteOnlyProperty<T> = DelegateSetterLazyOf(lazyReceiver, setter, initializedValue)
// 方法快捷创建Setter代理
@JvmName("delegateSetterLazy")
fun <T, R> KFunction2<R, T, Unit>.delegatorLazy(
    initializedValue: T? = null,
    lazyReceiver: () -> R
): WriteOnlyProperty<T> = DelegateSetterLazyOf(lazyReceiver, this, initializedValue)

internal class DelegateSetterLazyOf<T, R>(
    lazyReceiver: () -> R,
    setter: (R, T) -> Unit,
    initializedValue: T? = null
) : AbsObjectSetterPropertyDelegate1<R, T>(setter) {
    constructor(lazyReceiver: () -> R, property: KMutableProperty1<R, T>)
            : this(lazyReceiver, property::set)

    override val receiver: R by lazy {
        lazyReceiver().also { receiver ->
            initializedValue?.let { setter.invoke(receiver, it) }
        }
    }
}

internal abstract class AbsObjectSetterPropertyDelegate1<R, T>(
    private val setter: (R, T) -> Unit
) : WriteOnlyProperty<T>(), Serializable {
    protected abstract val receiver: R
    override fun setValue(thisRef: Any, property: KProperty<*>, value: T) =
        setter.invoke(receiver, value)
}

abstract class WriteOnlyProperty<V> : ReadWriteProperty<Any, V> {
    final override fun getValue(thisRef: Any, property: KProperty<*>): V =
        throw NoSuchMethodException("The value of ${property.name} can't be get!")
}

3、仅提供Getter、Setter代理

// 通用创建Getter、Setter代理
fun <T, R> delegateLazyOf(
    getter: (R) -> T,
    setter: (R, T) -> Unit,
    initializedValue: T? = null,
    lazyReceiver: () -> R
): ReadWriteProperty<Any, T> = DelegateLazyOf(lazyReceiver, getter, setter, initializedValue)
// 属性快捷创建Getter、Setter代理
fun <T, R> KMutableProperty1<R, T>.delegatorLazy(
    initializedValue: T? = null,
    lazyReceiver: () -> R
): ReadWriteProperty<Any, T> = DelegateLazyOf(lazyReceiver, this, initializedValue)

internal class DelegateLazyOf<T, R>(
    lazyReceiver: () -> R,
    getter: (R) -> T,
    setter: (R, T) -> Unit,
    initializedValue: T? = null
) : AbsObjectPropertyDelegate1<R, T>(getter, setter) {
    constructor(
        lazyReceiver: () -> R,
        property: KMutableProperty1<R, T>,
        initializedValue: T? = null
    ) : this(lazyReceiver, property::get, property::set, initializedValue)

    override val receiver: R by lazy {
        lazyReceiver().also { receiver ->
            initializedValue?.let { setter.invoke(receiver, it) }
        }
    }
}

internal abstract class AbsObjectPropertyDelegate1<R, T>(
    private val getter: (R) -> T,
    private val setter: (R, T) -> Unit
) : ReadWriteProperty<Any, T>, Serializable {
    protected abstract val receiver: R
    final override fun getValue(thisRef: Any, property: KProperty<*>): T = getter.invoke(receiver)
    final override operator fun setValue(thisRef: Any, property: KProperty<*>, value: T) =
        setter.invoke(receiver, value)
}

四、示例代码

// RealClazz
class RealClazz(var name: String) {
    val age: Int = 18
    private var value: Int = 0
    fun setScore(score: Int) { this.value = score }
    fun getScore(): Int = this.value
    override fun toString() = "[name=$name, age=$age, score=$value]"
}
object Person {
    private val realClazz = RealClazz("小明")
    fun printlnRealClazz() = println(realClazz)

    // --- 无接收者,饿汉式代理 ------------------------------------------
    val age by delegateOf(realClazz::age::get)
    var nameSetter by delegateOf(realClazz::name::set)
    var name by delegateOf(realClazz::name::get, realClazz::name::set)
    // -- 属性 --
    val ageProperty by realClazz::age.delegator()
    var nameProperty by realClazz::name.delegator()
    // -- 方法 --
    val scoreGetter by realClazz::getScore.delegator()
    var scoreSetter by realClazz::setScore.delegator()

    // --- 有接收者,饿汉式代理 ------------------------------------------
    val rAge by delegateOf(realClazz, RealClazz::age::get)
    var rNameSetter by delegateOf(realClazz, RealClazz::name::set)
    var rName by delegateOf(realClazz, RealClazz::name::get, RealClazz::name::set)
    // -- 属性 --
    val rAgeProperty by RealClazz::age.delegator(realClazz)
    var rNameProperty by RealClazz::name.delegator(realClazz)
    // -- 方法 --
    val rScoreGetter by RealClazz::getScore.delegator(realClazz)
    var rScoreSetter by RealClazz::setScore.delegator(realClazz)

    // --- 有接收者,懒汉式代理 ------------------------------------------
    val rAgeLazy by delegateLazyOf(RealClazz::age::get) { realClazz }
    var rNameSetterLazy by delegateLazyOf(RealClazz::name::set) { realClazz }
    var rNameLazy by delegateLazyOf(RealClazz::name::get, RealClazz::name::set) { realClazz }
    // -- 属性 --
    val rAgePropertyLazy by RealClazz::age.delegatorLazy { realClazz }
    var rNamePropertyLazy by RealClazz::name.delegatorLazy { realClazz }
    // -- 方法 --
    val rScoreGetterLazy by RealClazz::getScore.delegatorLazy { realClazz }
    var rScoreSetterLazy by RealClazz::setScore.delegatorLazy { realClazz }
}
fun main() {
    // --- 无接收者,饿汉式代理 ------------------------------------------
    Person.age.also { println("(age=$it)") } // (age=18)
    Person.nameSetter = "张三"
    Person.printlnRealClazz() //[name=张三, age=18, score=0]
    Person.name = "小六子"
    Person.name.also(::println) // 小六子
    // -- 属性 --
    Person.ageProperty.apply(::println) // 18
    Person.nameProperty = "李四"
    Person.nameProperty.apply(::println) // 李四
    // -- 方法 --
    Person.scoreSetter = 21
    Person.scoreGetter.apply(::println) // 21
    Person.printlnRealClazz() //[name=李四, age=18, score=21]
    println("======================================================")
    // --- 有接收者,饿汉式代理 ------------------------------------------
    Person.rAge.also { println("(age=$it)") } // (age=18)
    Person.rNameSetter = "张三"
    Person.printlnRealClazz() //[name=张三, age=18, score=21]
    Person.rName = "小六子"
    Person.rName.also(::println) // 小六子
    // -- 属性 --
    Person.rAgeProperty.apply(::println) // 18
    Person.rNameProperty = "李四"
    Person.rNameProperty.apply(::println) // 李四
    // -- 方法 --
    Person.rScoreSetter = 42
    Person.rScoreGetter.apply(::println) // 42
    Person.printlnRealClazz() //[name=李四, age=18, score=42]
    println("======================================================")
    // --- 有接收者,懒汉式代理 ------------------------------------------
    Person.rAgeLazy.also { println("(age=$it)") } // (age=18)
    Person.rNameSetterLazy = "张三"
    Person.printlnRealClazz() //[name=张三, age=18, score=42]
    Person.rNameLazy = "小六子"
    Person.rNameLazy.also(::println) // 小六子
    // -- 属性 --
    Person.rAgePropertyLazy.apply(::println) // 18
    Person.rNamePropertyLazy = "李四"
    Person.rNamePropertyLazy.apply(::println) // 李四
    // -- 方法 --
    Person.rScoreSetterLazy = 84
    Person.rScoreGetterLazy.apply(::println) // 84
    Person.printlnRealClazz() //[name=李四, age=18, score=84]

    // 特殊情况测试,由于我们提供了只有setter的情况,而这中情况只能用var接收,
    // 这就导致此属性代理getter情况可能被执行,如果无调用编译时应抛出异常。
    try {
        val name = Person.nameSetter
    } catch (e: Exception) {
        e.printStackTrace()
        println("======================================================")
    }
    try {
        val name = Person.rNameSetter
    } catch (e: Exception) {
        e.printStackTrace()
        println("======================================================")
    }
    try {
        val name = Person.rNameSetterLazy
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

运行结果:

(age=18)
[name=张三, age=18, score=0]
小六子
18
李四
21
[name=李四, age=18, score=21]
======================================================
(age=18)
[name=张三, age=18, score=21]
小六子
18
李四
42
[name=李四, age=18, score=42]
======================================================
(age=18)
[name=张三, age=18, score=42]
小六子
18
李四
84
[name=李四, age=18, score=84]
java.lang.NoSuchMethodException: The value of nameSetter can't be get!
    at com.lak.app.util.WriteOnlyProperty.getValue(Delegates.kt:138)
    at com.lak.app.test.Person.getNameSetter(Delegates.kt)
    at com.lak.app.test.DelegatesKt.main(Delegates.kt:104)
    at com.lak.app.test.DelegatesKt.main(Delegates.kt)
java.lang.NoSuchMethodException: The value of rNameSetter can't be get!
======================================================
    at com.lak.app.util.WriteOnlyProperty.getValue(Delegates.kt:138)
    at com.lak.app.test.Person.getRNameSetter(Delegates.kt)
    at com.lak.app.test.DelegatesKt.main(Delegates.kt:110)
    at com.lak.app.test.DelegatesKt.main(Delegates.kt)
======================================================
java.lang.NoSuchMethodException: The value of rNameSetterLazy can't be get!
    at com.lak.app.util.WriteOnlyProperty.getValue(Delegates.kt:138)
    at com.lak.app.test.Person.getRNameSetterLazy(Delegates.kt)
    at com.lak.app.test.DelegatesKt.main(Delegates.kt:116)
    at com.lak.app.test.DelegatesKt.main(Delegates.kt)

相关文章

网友评论

      本文标题:Kotlin实现自定义属性对其它属性及方法的代理

      本文链接:https://www.haomeiwen.com/subject/cmxtaktx.html