Kotlin委托
委托
委托 == 代理
方法内的成员永远拿不到thisRef:官方委托和自定义委托-》方法里面没办法使用反射
委托只能类委托和属性委托
Kotlin委托
本文链接:https://blog.csdn.net/feather_wch/article/details/132095759
类委托
1、类委托
- 委托的是接口的方法
// 只能用于接口
interface DB{fun save()
}
// 类CreateDBAction实现了接口DB,参数db是DB类型,类的实现委托给参数db。
// 目的:啥也不想干
class CreateDBAction(db: DB):DB by db
2、类委托的原理是什么?生成了什么代码?
- 成员变量:$$delegate_0 = 参数db
- 实现方法:委托给$$delegate_0调用save()
public final class CreateDBAction implements DB {// $FF: synthetic fieldprivate final DB $$delegate_0;public CreateDBAction(@NotNull DB db) {Intrinsics.checkNotNullParameter(db, "db");super();this.$$delegate_0 = db;}public void save() {this.$$delegate_0.save();}
}
3、类委托有什么用?
- 减少委托的代码
- Compose是重委托
CreateDBAction(SqlDB()).save()
CreateDBAction(OracleDB()).save()
属性委托
1、属性委托,委托的是 属性的 set和get
class MyKt{var value = 1314var number by ::value // 两个属性公用get和set
}
// number -> getNumber() -> getValue()
// number = 10 -> setNumber(10) -> setValue(10)
2、委托属性有什么用?
- 字段升级,老字段适配老用户,新字段用于新用户。共用一个get、set
class Database{var data = 941226 // 1.0var newData by ::data // 2.0
}
3、懒加载委托也就是属性委托
- 第一次获取时,才会获取,下面例子第一次获取耗时2秒,其他都立马获得
fun requestDownload(): String{Thread.sleep(2000L)return "sucess"
}// 懒加载,
// 属性委托,委托给
val responseData : String by lazy {requestDownload()
}
// val responseData : String = SynchronizedLazyImpl(requestDownload())
// 借助了SynchronizedLazyImpl的get方法fun main(){println("startloading...")println(responseData)println(responseData)println(responseData)
}
自定义属性委托
1、完全自己实现属性委托
// 自定义委托,定义好get和set之后,属性可以用该类实现属性委托
class Custom{operator fun getValue(owner: Owner, property: KProperty<*>) : String{return "AAA"}operator fun setValue(owner: Owner, property: KProperty<*>, value :String){}
}
class Owner{val responseData : String by Custom()
}
2、利用模板实现属性委托:ReadWriteProperty
// 自定义委托
class Custom2 : ReadWriteProperty<Owner, String>{var str = "default"override fun getValue(thisRef: Owner, property: KProperty<*>): String {return str}override fun setValue(thisRef: Owner, property: KProperty<*>, value: String) {str = value}
}
提供委托/暴露者委托
1、provideDelegate
- 额外的属性初始化逻辑:在属性被委托对象初始化之前进行一些额外的操作,例如数据验证、计算或日志记录等。
- 针对不同属性的不同行为:通过在不同的委托对象的provideDelegate方法中实现不同的逻辑,可以根据属性的不同需求,为每个属性提供不同的行为。
- 属性访问的可扩展性:可以为属性访问添加自定义的行为,例如缓存、延迟加载、权限控制等。
class Owner{val responseData : String by Custom()
}
// 自定义委托
class Custom(var str: String = "Default") : ReadWriteProperty<Owner, String>{override fun getValue(thisRef: Owner, property: KProperty<*>): String {return str}override fun setValue(thisRef: Owner, property: KProperty<*>, value: String) {str = value}
}
// provideDelegate,暴露者委托,== 选择器
class SmartDelegator{operator fun provideDelegate(thisRef:Owner, property: KProperty<*>):ReadWriteProperty<Owner, String>{return if(property.name.isEmpty()){Custom("empty")}else{Custom("normal")}}
}
实战场景
自己实现by lazy
class LazyInitDelegate<T> {private var initializer: (() -> T)? = nulloperator fun getValue(thisRef: Any?, property: KProperty<*>): T {return initializer?.invoke() ?: throw IllegalStateException("Property not initialized")}operator fun setValue(thisRef: Any?, property: KProperty<*>, value: (() -> T)) {initializer = value}
}class Example {val lazyProperty: String by LazyInitDelegate {// 在第一次访问属性时执行初始化逻辑println("Initializing lazy property")"Lazy Initialized"}
}fun main() {val example = Example()println(example.lazyProperty) // 输出:Initializing lazy property \n Lazy Initialized
}
属性委托的日志记录
import kotlin.reflect.KMutableProperty
import kotlin.reflect.KPropertyclass LoggingDelegate<T> {operator fun getValue(thisRef: Any?, property: KProperty<*>): T {val value = property.getter.call()println("Property ${property.name} is accessed, value: $value")return value as T}operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {println("Property ${property.name} is set with value: $value")(property as KMutableProperty).setter.call(thisRef, value)}
}class Example {var property: String by LoggingDelegate()
}fun main() {val example = Example()example.property = "New value" // 输出:Property property is set with value: New valueprintln(example.property) // 输出:Property property is accessed, value: New value \n New value
}
viewmodel
1、如何做到属性内部可以修改,外部不可以修改?
class Data{var data:String = ""private setprivate void changeData(value:String){data = value}
}
val data = Data()
data.data = "" // xxx 不可以
println(data.data) // 可以
2、如何做到kotlin的list集合,对内可以修改,对外界不可以修改
class MyKt{// 内部可以修改private val _data : MutableList<String> = mutableListOf()// 外部不可以修改val data : List<String> by :: _data
}
3、使用::用官方自定义委托,不使用需要自定义委托
4、用委托实现ViewModel的自动构造
class MyViewModel : ViewModel() {}fun main() {// 委托实现val mainViewModel : MyViewModel by viewModels()
}private fun MainActivity.viewModels() : ReadOnlyProperty<MainActivity?, MyViewModel> =object : ReadOnlyProperty<MainActivity?, MyViewModel>{override fun getValue(thisRef: MainActivity?, property: KProperty<*>): MyViewModel {// thisRef永远为nullreturn ViewModelProvider(this@viewModels).get(MyViewModel::class.java)}}
委托TextView:类似DataBinding
//
operator fun TextView.provideDelegate(value: Any?, property: KProperty<*>) =object: ReadWriteProperty<Any?, String?>{override fun getValue(thisRef: Any?, property: KProperty<*>): String? {return text as String}override fun setValue(thisRef: Any?, property: KProperty<*>, value: String?) {text = value}}// 创建TextView控件,双向绑定
var textView : TextView = findViewById(R.id.tv)
var message:String ? by textViewtextView.text = "更改了控件的text -> message中的数值也会变"message = "更改了数据 -> 更新UI"
双向绑定,多个控件操作数据
var data1 : String by textView1
var data2 : String by textView2
var data3 : String by textView3data3 = data2
data2 = data1
data1 = "我在吃饭哦"
// 操作数据,View就会变,不用管UI刷新数据
出题目:如何手动实现String的代理(局部变量)?(用扩展函数)
var s1 = "wch"
var s2 : String by ::s1 // 类的成员变量才可以
var s3 : String by s1 // 不用官方的::fun main() {var s1 = "wch"var s2:String by s1 // 报错
}
// Kotlin反射机制
operator fun String.setValue(item: Any?, property: KProperty<*>, value:String){// import kotlin.reflect.jvm.javaField, 已经被移除// property.javaField?.isAccessible = true// property.javaField?.set(item, value)
}
operator fun String.getValue(item: Any?, property: KProperty<*>) = this
相关文章:
Kotlin委托
委托 委托 代理 方法内的成员永远拿不到thisRef:官方委托和自定义委托-》方法里面没办法使用反射 委托只能类委托和属性委托 Kotlin委托 本文链接:https://blog.csdn.net/feather_wch/article/details/132095759 类委托 1、类委托 委托的是接口的方…...
分布式协议与算法——CAP理论、ACID理论、BASE理论
CAP理论 CAP理论,对分布式系统的特性做了高度抽象,比如抽象成了一致性、可用性和分区容错性,并对特性间的冲突(也就是CAP不可能三角)做了总结。 CAP三指标 CAP理论对分布式系统的特性做了高度抽象,形成了…...
接口测试 Jmeter 接口测试 —— 请求 Headers 与传参方式
一、 背景: 在使用 Jmeter 进行接口测试时,有些小伙伴不知道 Headers 和请求参数 (Parameters,Body Data) 的联系,本文主要讲 Content-Type 为 application/x-www-form-urlencoded 和 application/json 的场景。 1、使用 Parame…...
【redis】redis部署1主2从3哨兵demo搭建示例
redis版本为7,搭建的架构为1主2从3哨兵的架构。本文是对搭建的过程做一个回忆,过程可能遗漏了某些步骤,见谅。 首先,需要有一个已经安装了的redis。我们从redis源码目录中,找到一个redis.conf文件,这个文件…...
C++数据结构之平衡二叉搜索树(一)——AVL的实现(zig-zag/左右双旋/3+4重构)
目录 00.BBST——平衡二叉搜索树01.AVL树02.AVL的插入2.1单旋——zig 与 zag2.2插入节点后的单旋实例2.3手玩小样例2.4双旋实例2.5小结 03.AVL的删除3.1单旋删除3.2双旋删除3.3小结 04.34重构05.综合评价AVL5.1优点5.2缺点 00.BBST——平衡二叉搜索树 本文是介绍众多平衡二叉搜…...
免疫疗法勘察兵——DC细胞
DC细胞又叫树状细胞或者树突细胞,1869年由保罗兰格尔翰斯发现,一开始被误以为是神经细胞的一种,直到1973年皮肤科医师Inga Silberberg发现了他的免疫功能,同年,被拉尔夫斯坦曼和赞威尔A科恩两人正式命名为“dendritic…...
Django实现音乐网站 ⑷
使用Python Django框架制作一个音乐网站,在系列文章3的基础上继续开发, 本篇主要是后台歌曲类型表、歌单表模块功能开发。 目录 表结构设计 歌曲类型表结构 歌单表结构 创建表模型 创建表 后台注册表模型 引入表模型 后台自定义 总结 表结构设计…...
2023年华数杯数学建模C题思路 - 母亲身心健康对婴儿成长的影响
# 1 赛题 C 题 母亲身心健康对婴儿成长的影响 母亲是婴儿生命中最重要的人之一,她不仅为婴儿提供营养物质和身体保护, 还为婴儿提供情感支持和安全感。母亲心理健康状态的不良状况,如抑郁、焦虑、 压力等,可能会对婴儿的认知、情…...
openGauss学习笔记-30 openGauss 高级数据管理-别名
文章目录 openGauss学习笔记-30 openGauss 高级数据管理-别名30.1 语法格式30.1.1 列别名语法30.1.2 表别名语法 30.2 参数说明30.3 示例 openGauss学习笔记-30 openGauss 高级数据管理-别名 SQL可以重命名一张表或者一个字段的名称,这个名称为该表或该字段的别名。…...
C#实现多线程局域网扫描器的思路与具体代码
C#实现多线程局域网扫描器的思路与具体代码 思路: 获取局域网内所有 IP 地址遍历所有 IP 地址,使用 Ping 命令测试主机是否在线如果主机在线,则扫描主机上的所有端口,确定哪些端口是开放的输出扫描结果 在上述过程中࿰…...
Redis秒杀:一人一单问题及初步解决
优惠券秒杀一人一单 前言一、需求以及之前存在的问题二、增加一人一单逻辑1.初步代码2.封装一人一单逻辑3.控制锁的粒度 三、事务控制问题四、总结 前言 跟随黑马虎哥学习redis: 这是我认为b站上最好的redis教程,各方面讲解透彻,知识点覆盖…...
python 数据分析面试题:求分组排第n名的记录数据
近期面试遇到一个面试题,分享给大家。 文中会提供详细的解题思路以及问题延伸 一、面试题 面试题:输出各学科总分第一名的学员姓名、年龄、分数数据: class_a {name: [学员1, 学员2, 学员3, 学员4,学员5],age: [23, 24, 26, 27,25],course…...
eclipse常用快捷键
Eclipse常用快捷键 补全代码的声明:alt /快速修复: ctrl 1批量导包:ctrl shift o使用单行注释:ctrl /使用多行注释: ctrl shift /取消多行注释:ctrl shift \复制指定行的代码:ctrl alt down 或…...
什么是OCR?OCR技术详解
光学字符识别(Optical Character Recognition)简称为“OCR”。ORC是指对包含文本资料的图像文件进行分析识别处理,获取文字及版面信息的技术。 一般包括以下几个过程: 1.图像输入 针对不同格式的图像,有着不同的存储格式和压缩方式。目前&…...
【大模型】开源且可商用的大模型通义千问-7B(Qwen-7B)来了
【大模型】开源且可商用的大模型通义千问-7B(Qwen-7B)来了 新闻通义千问 - 7B 介绍评测表现快速使用环境要求安装相关的依赖库推荐安装flash-attention来提高你的运行效率以及降低显存占用使用 Transformers 运行模型使用 ModelScope 运行模型 量化长文本…...
SQL分类及通用语法数据类型
一、SQL分类 DDL: 数据定义语言,用来定义数据库对象(数据库、表、字段)DML: 数据操作语言,用来对数据库表中的数据进行增删改DQL: 数据查询语言,用来查询数据库中表的记录DCL: 数据控制语言,用来创建数据库…...
亿欧智库:2023中国功效型护肤产品成分解析研究报告(附下载
关于报告的所有内容,公众【营销人星球】获取下载查看 核心观点 消费端:“纯净美妆〞概念火热,消费驱动因素向成分来源硬核转变 新冠疫情过后,消费者对于生活健康:自然,可持续的关注度持续上升。在消费者…...
Kubernetes高可用集群二进制部署(一)主机准备和负载均衡器安装
Kubernetes概述 使用kubeadm快速部署一个k8s集群 Kubernetes高可用集群二进制部署(一)主机准备和负载均衡器安装 Kubernetes高可用集群二进制部署(二)ETCD集群部署 Kubernetes高可用集群二进制部署(三)部署…...
python与深度学习(十二):CNN和猫狗大战二
目录 1. 说明2. 猫狗大战的CNN模型测试2.1 导入相关库2.2 加载模型2.3 设置保存图片的路径2.4 加载图片2.5 图片预处理2.6 对图片进行预测2.7 显示图片 3. 完整代码和显示结果4. 多张图片进行测试的完整代码以及结果 1. 说明 本篇文章是对上篇文章猫狗大战训练的模型进行测试。…...
React(1)——快速入门
目录 一、React背景简介 ❤️ 官网和资料 📚 介绍描述 🐧 React的特点 🔨 React高效的原因 🙏🏻 二、React的基本使用 💻 三、React JSX(JSX:JavaScript XML)📦 …...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
