Kotlin之提供委托
时间:2022-04-27
本文章向大家介绍Kotlin之提供委托,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
通过定义 provideDelegate 操作符,可以扩展创建属性实现所委托对象的逻辑。 如果 by 右侧所使用的对象将 provideDelegate 定义为成员或扩展函数,那么会调用该函数来 创建属性委托实例。
provideDelegate 的一个可能的使用场景是在创建属性时(而不仅在其 getter 或 setter 中)检查属性一致性。例如,如果要在绑定之前检查属性名称,可以这样写:
class ResourceLoader<T>(id: ResourceID<T>) {
operator fun provideDelegate(
thisRef: MyUI,
prop: KProperty<*>
): ReadOnlyProperty<MyUI, T> {
checkProperty(thisRef, prop.name)
// 创建委托
}
private fun checkProperty(thisRef: MyUI, name: String) { …… }
}
fun <T> bindResource(id: ResourceID<T>): ResourceLoader<T> { …… }
class MyUI {
val image by bindResource(ResourceID.image_id)
val text by bindResource(ResourceID.text_id)
}
provideDelegate 的参数与 getValue 相同:
- thisRef —— 必须与 属性所有者 类型(对于扩展属性——指被扩展的类型)相同或者是它的超类型。
- property —— 必须是类型 KProperty<*> 或其超类型。 在创建 MyUI 实例期间,为每个属性调用provideDelegate 方法,并立即执行必要的验证。
如果没有这种拦截属性与其委托之间的绑定的能力,为了实现相同的功能, 你必须显式传递属性名,这不是很方便:
// 检查属性名称而不使用“provideDelegate”功能
class MyUI {
val image by bindResource(ResourceID.image_id, "image")
val text by bindResource(ResourceID.text_id, "text")
}
fun <T> MyUI.bindResource(
id: ResourceID<T>,
propertyName: String
): ReadOnlyProperty<MyUI, T> {
checkProperty(this, propertyName)
// 创建委托
}
在生成的代码中,会调用 provideDelegate 方法来初始化辅助的 prop$delegate 属性。 比较对于属性声明 val prop: Type by MyDelegate() 生成的代码与 上面(当 provideDelegate 方法不存在时)生成的代码:
class C {
var prop: Type by MyDelegate()
}
// 这段代码是当“provideDelegate”功能可用时,由编译器生成的代码:
class C {
// 调用“provideDelegate”来创建额外的“delegate”属性
private val prop$delegate = MyDelegate().provideDelegate(this, this::prop)
val prop: Type
get() = prop$delegate.getValue(this, this::prop)
}
请注意,provideDelegate 方法只影响辅助属性的创建,并不会影响为 getter 或 setter 生成的代码。
上面例子的完整代码为:
fun main(args: Array<String>) {
val myui: MyUI = MyUI()
println(myui.image)
}
class dge<T>(t: T) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, 这里委托了 ${property.name} 属性"
}
}
class ResourceLoader<T>(id: Int) {
operator fun provideDelegate(
thisRef: MyUI,
prop: KProperty<*>
): dge<T?> {
checkProperty(thisRef, prop.name)
// 创建委托
var t: T? = null
return dge(t)
}
private fun checkProperty(thisRef: MyUI, name: String) {
println(name)
}
}
fun <T> bindResource(id: Int): ResourceLoader<T> {
return ResourceLoader<T>(id)
}
class MyUI {
val image by bindResource<String>(1)
val text by bindResource<String>(2)
}
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 完美解决-RuntimeError: CUDA error: device-side assert triggered
- springmvc之异常处理SimpleMappingExceptionResolver
- 剑指offer(13-15)题解
- 【leetCode】青蛙跳台问题(这只青蛙会托马斯大旋转)day07
- 【leetCode】斐波那契数列day06
- 剑指offer(61-67)题解
- 宇智波程序笔记8-【高并发】ThreadLocal学会了这些,你也能和面试官扯皮了!
- 情感分析数据预处理过程
- java的内部类和静态内部类(嵌套类)
- python爬取B站视频弹幕分析并制作词云
- mybatis扩展之自定义类型处理器处理枚举类型
- IMDB影评数据集预处理(使用word2vec)
- 【leetCode】使用两个栈搞一个队列day05
- bert训练代码
- mybatis文件映射之自定义返回结果集