kotlin代理

委托代理

在kotlin里面代理都是通过by关键字来实现得。代理顾名思义就是重写setValue方法和getValue方法,将某一类型得数据按照我们设计好的某种工厂方式加工出来。比如by lazy,我们希望使用他的代理都可以实现懒加载得功能,帮助开发者省下每次都要写懒加载得方式。

实现代理得思路就是重写setVaule方法和getValue方法。如果是var声明的变量那么就可以重写setValue和getValue。如果是val声明的就只能重写getValue。当然我们还可以自定义提供委托需要重载方法provideDelegate操作符。可以扩展创建属性实现所委托对象的逻辑。

这里先来演示一个简单的,代理getVaule和setValue:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import kotlin.reflect.KProperty

class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, thank you for delegating '${property.name}' to me!"
}

operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$value has been assigned to '${property.name}' in $thisRef.")
}
}

class Example {
var p: String by Delegate()
}
fun main(){
val e = Example()
println(e.p) //Example@33a17727, thank you for delegating ‘p’ to me!
e.p = "NEW" //NEW has been assigned to ‘p’ in Example@33a17727.

}

属性委托要求:

对于val: 委托必须提供一个操作符函数 getValue(),该函数具有以下参数:

  • thisRef —–必须与属性所有者类型(对于扩展属性–指被扩展的类型)相同或者是其超类

  • property—— 必须是类型KProperty<*>` 或其超类型。

1
2
3
4
5
6
7
8
9
class Resource
class Owner {
val valResource: Resource by ResourceDelegate()
}
class ResourceDelegate {
operator fun getValue(thisRef: Owner, property: KProperty<*>): Resource {
return Resource()
}
}

对于var委托必须额外提供一个操作符函数 setValue(), 该函数具有以下参数:

  • thisRef —— 必须与 属性所有者 类型(对于扩展属性——指被扩展的类型)相同或者是其超类型。
  • property —— 必须是类型 KProperty<*> 或其超类型。
  • value — 必须与属性类型相同(或者是其超类型)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Resource

class Owner {
var varResource: Resource by ResourceDelegate()
}

class ResourceDelegate(private var resource: Resource = Resource()) {
operator fun getValue(thisRef: Owner, property: KProperty<*>): Resource {
return resource
}
operator fun setValue(thisRef: Owner, property: KProperty<*>, value: Any?) {
if (value is Resource) {
resource = value
}
}
}

# 提供委托

provideDelegate 的参数与 getValue 相同:

  • thisRef —— 必须与 属性所有者 类型(对于扩展属性——指被扩展的类型)相同或者是它的超类型;
  • property —— 必须是类型 KProperty<*> 或其超类型。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
class ResourceDelegate<T>(var num:T) : ReadOnlyProperty<MyUI, T> {
override fun getValue(thisRef: MyUI, property: KProperty<*>): T {
return num
}
}

class ResourceLoader<T>(var id: Teacher<T>) {
operator fun provideDelegate(
thisRef: MyUI,
prop: KProperty<*>
): ReadOnlyProperty<MyUI, T> {
checkProperty(thisRef, prop.name)
// 创建委托
return ResourceDelegate(id.tNum)
}

private fun checkProperty(thisRef: MyUI, name: String) {

}
}

class MyUI {
fun <T> bindResource(id: Teacher<T>): ResourceLoader<T> {
return ResourceLoader<T>(id)
}

val image by bindResource(Teacher<Int>(150))
}

fun main(){
var s = MyUI()
System.out.println(s.image)
}