当前位置: 首页 > news >正文

解析Kotlin中的委托(包括类委托,属性委托)【笔记摘要】

1.委托模式

委托模式:操作对象不会去处理某段逻辑,而是会把工作委托给另外一个辅助对象去处理。
例如我们要设计一个自定义类的来实现Set,可以将该实现委托给另一个对象:

class MySet<T> (val helperSet: HashSet<T>) : Set<T> {override val size: Intget() = helperSet.sizeoverride fun isEmpty(): Boolean {return helperSet.isEmpty()}override fun iterator(): Iterator<T> {return helperSet.iterator()}override fun containsAll(elements: Collection<T>) = helperSet.containsAll(elements)override fun contains(element: T) = helperSet.contains(element)override fun contains(element: T) = false  //自己重写该方法来定制功能fun eat() = println("I can eat.")  //新增方法
}

这样就可以让大部分的方法实现调用辅助对象中的方法,少部分的方法实现由自己来重写,甚至加入一些自己独有的方法,那么MySet就会成为一个全新的数据结构类

2.类委托

如上委托模式的代码实现存在一个弊端,如果接口中待实现的方法特别多,那么相应每个都去调用辅助对象中的相应方法实现将会特别复杂
这时候在Kotlin中使用by关键字,再接上受委托的辅助对象,就可以免去之前所写的一大堆模板式的代码了:

class MySet<T>(val helperSet: HashSet<T>) : Set<T> by helperSet {override fun contains(element: T) = false  //自己重写该方法来定制功能fun eat() = println("I can eat.")  //新增方法
}

类委托本质:简化实现委托模式所需要写的很多不必要代码

3.类可以委托给对象的情况

可以的情况:

 a.构造函数中传入
class MyList2(theList: ArrayList<String>) : List<String> by theList {
}
 b.object的属性
class MyList3 : List<String> by theList {object theList : ArrayList<String>()
}
 c.伴生对象中的属性
class MyList4 : List<String> by theList {companion object {val theList: List<String> = ArrayList<String>()}
}
 d.直接创建对象
class MyList6 : List<String> by ArrayList() {
}
 e.调用函数获得对象
fun getDdd() : LinkedList<String> {return LinkedList<String>()
}    class MyList7 : List<String> by getDdd() {
}


不可以的情况:

 a.字段
class MyList : List<String> by theList {  //编译报错,提示:Unresolved reference: theListval theList: List<String> = ArrayList<String>()
}
 b.构造函数中的变量
class MyList8 : List<String> by theList {   //编译报错,提示:Unresolved reference: theListinit {val theList = ArrayList<String>()}
}

4.属性委托

属性委托的核心思想是将一个属性(字段)的具体实现委托给另一个对象去完成
可以看到,这里使用by关键字连接了左边的p属性和右边的Delegate类去完成。当调用p属性的时候会自动调用Delegate的getValue()方法,当给p属性赋值的时候会自动调用Delegate类的setValue()方法

class MyClass {var p by Delegate()
}

Delegate的具体实现:在Delegate类中我们必须实现getValue()和setValue()这两个方法,并且都要使用operator关键字进行声明

class Delegate {var proValue: Any? = null//第一个参数用于声明该Delegate类的委托功能可以在什么类中使用//第二个参数是Kotlin中的一个属性操作类,可用于扩区各种属性相关的值,在当前场景用不着,但必须在方法参数上进行声明//返回值可以声明成【任何类型】,根据具体的实现逻辑去写就可以了operator fun getValue(myClass: MyClass, prop: KProperty<*>) : Any? {return proValue}//前两个参数和getValue()相同//最后一个参数表示具体要赋值给委托属性的值,这个参数类型必须要和getValue()方法返回值的类型保持一致operator fun setValue(myClass: MyClass, prop: KProperty<*>, value: Any?) {proValue = value}
}

现在当我们给p属性赋值时,就会调用Delegate的setValue()方法;当获取p属性的值时,就会调用Delegate类的getValue()方法
如果p属性是使用val关键字声明的,那么就不用在Delegate类中实现setValue()方法,因为它是常量


参考文章:
类声明的右边也能写 by?Kotlin 的接口委托是这么用的

http://www.lryc.cn/news/389829.html

相关文章:

  • vue3+ts+uniapp+vite+pinia项目配置
  • 大数据开发语言 Scala(四):面向对象编程
  • C++ //练习 14.31 我们的StrBlobPtr类没有定义拷贝构造函数、赋值运算符及析构函数,为什么?
  • 通配符和正则表达式之间的关系
  • GY-30光照传感器软件I2C方式驱动代码,基于STM32Cube
  • 双相元编程:一种新语言设计方法
  • 基于SpringBoot校园外卖配送系统设计和实现(源码+LW+调试文档+讲解等)
  • 茗鹤APS高级计划排程系统,在集团多工厂协同生产下的应用
  • 分享六款免费u盘数据恢复工具,U盘恢复工具集合【工具篇】
  • Linux 的启动流程
  • 思维导图插件--jsMind的使用
  • mac上使用finder时候,显示隐藏的文件或者文件夹
  • 泰雷茲具有首个通过FIPS 140-3 三级认证的HSMs
  • 美术馆预约小程序的设计
  • 序列化Serializable
  • 编写静态库
  • hive的表操作
  • 基于多视点编码光场的全景三维重建方法
  • Spring Boot中的分布式文件系统
  • three.js地理坐标系有哪些,和屏幕坐标系的转换。
  • 聊聊C++20的三向比较运算符 `<=>`
  • CVE-2024-0603 漏洞复现
  • 西部智慧健身小程序+华为运动健康服务
  • Spring Boot中如何处理异步任务
  • 数字化精益生产系统--RD研发管理系统
  • 鱼眼相机 去畸变
  • DC/AC电源模块:为智能家居设备提供恒定的电力供应
  • 小红书运营教程02
  • k8s自动清理节点服务
  • JS如何把年月日转为时间戳