分以下几类进行讲解
- 接口委托
- 延迟委托
- 引用委托
- 自定义委托
- 重写操作符setValue\getValue
- 实现接口ReadWriteProperty、ReadOnlyProperty
- 重写操作符provideDelegate
接口委托
将接口的实现委托给对应传入参数。
interface DB {
fun save()
}
class SqlDB() : DB {
override fun save() = println("save to sql")
}
class MySqlDB() : DB {
override fun save() = println("save to MySqlDB")
}
class OracleDB() : DB {
override fun save() = println("save to Oracle")
}
// 委托含义解释: 将接口的实现 委托给了参数db
class CreateDBAction(db: DB) : DB by db
fun main() {
CreateDBAction(SqlDB()).save()
CreateDBAction(OracleDB()).save()
CreateDBAction(MySqlDB()).save()
}
延迟委托
也是我们比较常见的,例如延迟初始化变量,等调用的时候再进行初始化
val lazySqlDB by lazy { SqlDB() }
引用委托
之前我们看的2种都是属于直接对象委托,但是我们想委托对应的引用咋整?可以使用双冒号代表引用地址 ::。
// var 可读 可改 内部会有 set get val 只有get 只读
var floatValue : Float = 123.45f
set(v) {
field = v
println("你设置了 floatValue哦 v:$v")
}
get() {
println("你获取了 floatValue哦")
return field
}
var number : Float by ::floatValue
自定义委托
重写操作符setValue\getValue
这个比较好理解,我们变量默认都会实现set\get,如果我们是以类来看,重写类的setValue和getValue
class Owner {
// var (自定义委托中,必须有 set get)
// String (自定义委托中,get返回String,set传入String)
// get/set方法 第一个参数 必须包含 本类Owner或Owner父类
var text: String by Simple()
var text2 : String by StringDelegate()
}
class Simple {
private var str: String = "Default"
operator fun getValue(owner: Owner, property: KProperty<*>) : String {
println("getValue执行啦")
return str
}
operator fun setValue(owner: Owner, property: KProperty<*>, value : String) {
println("setValue执行啦")
str = value
}
}
class StringDelegate() : ReadWriteProperty<Owner, String> {
private var str: String = "Default"
override fun getValue(thisRef: Owner, property: KProperty<*>): String {
println("ReadWriteProperty getValue执行啦")
return str
}
override fun setValue(thisRef: Owner, property: KProperty<*>, value: String) {
println("ReadWriteProperty setValue执行啦")
str = value
}
}
fun main() {
val o = Owner()
o.text = "自定义simple"
println(o.text)
o.text2 = "自定义 delegate"
println(o.text2)
}
以下是打印的内容
setValue执行啦
setValue执行对应value = 自定义simple
getValue执行啦
自定义simple
ReadWriteProperty setValue执行啦
ReadWriteProperty getValue执行啦
自定义 delegate
先看Simple,重写操作符operator对应的方法,从而实现自定义委托。ReadWriteProperty是个接口,接口内部实际上也是operator修饰的setValue/getValue,接着往下介绍ReadWriteProperty
实现接口ReadWriteProperty、ReadOnlyProperty
可以看下ReadWriteProperty、ReadOnlyProperty具体实现,前者是可读可写,后者是只读,前者继承后者
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)
}
public fun interface ReadOnlyProperty<in T, out V> {
public operator fun getValue(thisRef: T, property: KProperty<*>): V
}
具体源码实现不在本篇内容讲解,来说下ReadWriteProperty具体的参数含义。先说泛型<T,V>,以前面说的StringDelegate作为例子,T(Owner)也就是委托类具体类型,V(String)委托出去的具体类型
class Owner {
// 把Owner的text2(String类型)委托给StringDelegate
var text2 : String by StringDelegate()
}
// 第一个泛型被委托的类类型,第二个泛型被委托具体返回的类型
class StringDelegate() : ReadWriteProperty<Owner, String> {
private var str: String = "Default"
override fun getValue(thisRef: Owner, property: KProperty<*>): String {
println("ReadWriteProperty getValue执行啦")
return str
}
override fun setValue(thisRef: Owner, property: KProperty<*>, value: String) {
println("ReadWriteProperty setValue执行啦")
str = value
}
}
setValue/getValue的第一个参数就是第一个泛型,第二个参数是第二个泛型,这是固定写法。
重写操作符provideDelegate
重写类自带操作符函数provideDelegate返回类型是ReadWriteProperty,它可以做一个选择器,看一下代码理解
class StringDelegateUpdate(var str: String = "Default") : ReadWriteProperty<Owner2, String> {
override fun getValue(thisRef: Owner2, property: KProperty<*>): String {
println("ReadWriteProperty getValue执行啦")
return str
}
override fun setValue(thisRef: Owner2, property: KProperty<*>, value: String) {
println("ReadWriteProperty setValue执行啦")
str = value
}
}
class SmartDelegator {
// 相当于是一个选择器,动态选择 是哪个 StringDelegateUpdate自定义委托
operator fun provideDelegate(
thisRef : Owner2,
property: KProperty<*>) : ReadWriteProperty<Owner2, String> {
// 逻辑是自己决定的
return if (property.name.contains("aaa")) {
StringDelegateUpdate("bbb")
} else {
StringDelegateUpdate("aaa")
}
}
}
class Owner2 {
var aaa: String by SmartDelegator()
var bbb: String by SmartDelegator()
}
fun main() {
val owner = Owner2()
println(owner.aaa)
println(owner.bbb)
}
通过重写provideDelegate方法,来决定自己要使用那个ReadWriteProperty对象,从而实现自定义代理选择器