Kotlin 委托

Kotlin 委托

委托模式 是一种 通过 对象组合 实现代码重用 的设计模式,

对象处理请求时 将其 委托给 其他对象(委托)处理。

Kotlin 委托 分为:

  1. 类的委托
  2. 属性的委托

一、类的委托

委托 Delegate 是实现继承的一种替代方式。达到了 多继承、代码复用 目的。

我们知道Java本身不支持多继承的,而是通过 接口 实现多态。

接口每次都要实现,对于已有的代码实现 复用,可通过 委托实现类

通过 by 关键字, 来委托接口实现。

举例,Base 接口 委托实现:

kotlin 复制代码
interface Base {
    fun print()
}

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

// 通过 构造器 参数 委托
class Derived(b: Base) : Base by b
// 也可以 实例对象 委托
class Derived : Base by BaseImpl(10)

二、属性委托(Property delegate)

属性委托,通过 委托类 实现

  • operator fun getValue(thisRef, property)
  • operator fun setValue(thisRef, property, value)

方法 实现 委托属性的读写。

下面代码,实现属性委托:

Kotlin 复制代码
class Delegate(private var str: String) {

    operator fun getValue(ref: Any?, property: KProperty<*>): String {
        // 返回 属性值
        return str
    }

    operator fun setValue(ref: Any?, property: KProperty<*>, value: String) {
      // 进行赋值
      this.str = value
    }

}

class Owner {
    // 通过委托
    val p: String by Delegate()
}

方便 属性委托 实现,Kotlin标准库提供:

  • ReadOnlyProperty,对应 val 只读属性
  • ReadWriteProperty,对应 var 读写属性

属性的委托接口(可手写不使用此接口,仅为了方便)。

kotlin 复制代码
public interface ReadWriteProperty<in T, V> : ReadOnlyProperty<T, V> {

    public override operator fun getValue(thisRef: T, property: KProperty<*>): V

    public operator fun setValue(thisRef: T, property: KProperty<*>, value: V)
    
}

标准委托

Kotlin 有以下 委托 方法:

  1. 延迟属性 lazy
  2. 可观察属性 Delegates.observable 和 Delegates.vetoable
  3. 委托给其他属性
  4. Map属性
1. 延迟属性(Lazy properties)

延迟初始化,只有第一次调用时 执行 lazy{},后面直接返回 存储的值。

Kotlin 复制代码
// 延迟属性
val countData by lazy {
  MutableLiveData(0)
}
2. 可观察属性

每次属性赋值时,都会调用 handler 方法。

vetoableobservable 一样也是 赋值 时,调用 handler 方法。

但是 vetoable 是在 赋值前 调用,通过返回 true false 确定是否 赋值。

kotlin 复制代码
// 可观察属性,
val count by Delegates.observable(0) { _, old, new -> 
  println("print value, old: ${old}, new: ${new}")
}
// 是否设置新值 的 可观察属性
val count by Delegates.vetoable(0) { _, old, new -> 
  // 返回false,不更新值
  false
}

补充:

Delegates 还有 notNull<T>() 方法,创建一个非空的委托,不会在初始化赋值,

而是在后面进行初始值。在设置初始化值前,访问抛出IllegalStateException异常。

3. 委托给其他属性

将属性 委托 给其他属性 或 其他对象的属性。使用 :: 操作符来 引用 其他属性。

kotlin 复制代码
class MyClass {
   var newName: Int = 0
   @Deprecated("Use 'newName' instead", ReplaceWith("newName"))
   var oldName: Int by this::newName
}
4. Map委托

通用的场景把 属性值 存储在 map 中。

kotlin 复制代码
// Map,取 以 属性名 为 键的 值
class User(val map: Map<String, Any?>) {
    val name: String by map
    val age: Int     by map
}

// 如果希望可修改,使用 MutableMap
class User(val map: MutableMap<String, Any?>) {
    var name: String by map
    var age: Int     by map
}

文档

相关推荐
代码s贝多芬的音符2 小时前
ios android 小程序 蓝牙 CRC16_MODBUS
android·ios·小程序
应用市场2 小时前
构建自定义命令行工具 - 打造专属指令体
开发语言·windows·python
Dfreedom.3 小时前
一文掌握Python四大核心数据结构:变量、结构体、类与枚举
开发语言·数据结构·python·变量·数据类型
一半烟火以谋生3 小时前
Python + Pytest + Allure 自动化测试报告教程
开发语言·python·pytest
虚行3 小时前
C#上位机工程师技能清单文档
开发语言·c#
小羊在睡觉3 小时前
golang定时器
开发语言·后端·golang
CoderCodingNo4 小时前
【GESP】C++四级真题 luogu-B4068 [GESP202412 四级] Recamán
开发语言·c++·算法
Larry_Yanan4 小时前
QML学习笔记(四十四)QML与C++交互:对QML对象设置objectName
开发语言·c++·笔记·qt·学习·ui·交互
百锦再4 小时前
对前后端分离与前后端不分离(通常指服务端渲染)的架构进行全方位的对比分析
java·开发语言·python·架构·eclipse·php·maven
2501_915918414 小时前
iOS 混淆实战 多工具组合完成 IPA 混淆、加固与工程化落地(iOS混淆|IPA加固|无源码混淆|Ipa Guard|Swift Shield)
android·ios·小程序·https·uni-app·iphone·webview