当前位置: 首页 > 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 的接口委托是这么用的

相关文章:

  • 国家海岸线变化评估:新英格兰和中大西洋沿岸海岸线的历史变化
  • Handling `nil` Values in `NSDictionary` in Objective-C
  • 煤矿安全大模型:微调internlm2模型实现针对煤矿事故和煤矿安全知识的智能问答
  • 基于C#在WPF中使用斑马打印机进行打印
  • 58.鸿蒙系统app(HarmonyOS)(ArkUI)更改应用程序图标
  • UE5 动画蓝图
  • 计算机是如何看到图像的
  • 泰雷茲具有首个通过FIPS 140-3 三级认证的HSMs
  • 引领AI新时代:深度学习与大模型的关键技术
  • 探索大型语言模型自动评估 LLM 输出长句准确性的方法
  • Python面试宝典第4题:环形链表
  • 3099. 哈沙德数 Easy
  • 广州外贸建站模板
  • 中控室监控台在水处理行业的作用
  • C++实现简化版Qt的QObject(5):通过IEventLoopHost扩展实现win32消息循环
  • 【跃迁之路】【641天】程序员高效学习方法论探索系列(实验阶段398-2018.11.14)...
  • 4. 路由到控制器 - Laravel从零开始教程
  • ES学习笔记(12)--Symbol
  • express + mock 让前后台并行开发
  • Js实现点击查看全文(类似今日头条、知乎日报效果)
  • RxJS: 简单入门
  • SpringBoot几种定时任务的实现方式
  • tab.js分享及浏览器兼容性问题汇总
  • 产品三维模型在线预览
  • 初识MongoDB分片
  • 基于 Babel 的 npm 包最小化设置
  • 思否第一天
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • 学习使用ExpressJS 4.0中的新Router
  • PostgreSQL之连接数修改
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • ​Python 3 新特性:类型注解
  • $.ajax()方法详解
  • $GOPATH/go.mod exists but should not goland
  • $nextTick的使用场景介绍
  • (1)虚拟机的安装与使用,linux系统安装
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第5节(封闭类和Final方法)
  • (分布式缓存)Redis分片集群
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (三)uboot源码分析
  • (顺序)容器的好伴侣 --- 容器适配器
  • (转)shell中括号的特殊用法 linux if多条件判断
  • .Net Core缓存组件(MemoryCache)源码解析
  • .net 托管代码与非托管代码
  • .NET 应用启用与禁用自动生成绑定重定向 (bindingRedirect),解决不同版本 dll 的依赖问题
  • .NET/C# 判断某个类是否是泛型类型或泛型接口的子类型
  • .NET多线程执行函数
  • .net和php怎么连接,php和apache之间如何连接
  • @JSONField或@JsonProperty注解使用
  • @SuppressWarnings(unchecked)代码的作用
  • [ Linux ] Linux信号概述 信号的产生
  • [18] Opencv_CUDA应用之 基于颜色的对象检测与跟踪
  • [20171101]rman to destination.txt
  • [AUTOSAR][诊断管理][ECU][$37] 请求退出传输。终止数据传输的(上传/下载)