Plain's Blog

休想打败我的生活🔥

  1. 1. Lazy
    1. 1.1. 实现
    2. 1.2. 使用
    3. 1.3. 原理
  2. 2. Observable
    1. 2.1. 实现
    2. 2.2. 使用
  3. 3. NotNull
    1. 3.1. 实现
    2. 3.2. 使用
  4. 4. 参考文章
  5. 5. 示例地址

有一些常见的属性类型,虽然我们可以在每次需要的时候手动实现它们, 但是如果能够为大家把他们只实现一次并放入一个库会更好。

Lazy

实现

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// 默认值
internal object DEFAULT_VALUE

// 定义 Lazy 接口
interface FakeLazy<out T> {
public val value: T
// 是否初始化
public fun isInitialized(): Boolean
}

// 对外函数
fun <T> fakeLazy(initializer: () -> T): FakeLazy<T> = FakeLazyImpl(initializer)

// 对外扩展函数
// by fakeLazy {}
operator fun <T> FakeLazy<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value

// Lazy 实现类
// 线程安全🔐
@Suppress("UNCHECKED_CAST")
class FakeLazyImpl<out T>(private var initializer: (() -> T)?) : FakeLazy<T> {

@Volatile
private var _value: Any? = DEFAULT_VALUE
private val lock = this

override val value: T
get() {
// 第一步
// 首先判断当前的 value 是否是默认值
// 如果不是说明已经初始化过,直接返回
val _v1 = _value
if (_v1 !== DEFAULT_VALUE) {
return _v1 as T
}
synchronized(lock) {
// 第二步
// 加锁后,重复第一步判断
val _v2 = _value
if (_v2 !== DEFAULT_VALUE) {
return _v2 as T
} else {
// 第三步
// 以上条件都不满足,说明还未初始化
// 调用 initializer 函数进行初始化
val _v3 = initializer!!()
// 将初始化后的值赋给 value
_value = _v3
// 将初始化函数置空
initializer = null
return _v3
}
}
}

override fun isInitialized(): Boolean = _value !== DEFAULT_VALUE

}

使用

1
2
3
4
5
6
7
class FakeLazyDemo {

val instance by fakeLazy {
FakeLazyDemo()
}

}

原理

将上述代码反编译为 Java 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public final class FakeLazyDemo {
// $FF: synthetic field
static final KProperty[] $$delegatedProperties = new KProperty[]{(KProperty)Reflection.property1(new PropertyReference1Impl(Reflection.getOrCreateKotlinClass(FakeLazyDemo.class), "instance", "getInstance()Lcom/application/FakeLazyDemo;"))};
@NotNull
private final FakeLazy instance$delegate;

@NotNull
public final FakeLazyDemo getInstance() {
return (FakeLazyDemo)FakeLazyKt.getValue(this.instance$delegate, this, $$delegatedProperties[0]);
}

public FakeLazyDemo() {
this.instance$delegate = FakeLazyKt.fakeLazy((Function0)null.INSTANCE);
}
}

根据代码可以看到

  • 生成一个该属性的附加属性: instance$delegate

  • 构造器中,将使用 lazy(()->T) 创建的 Lazy 实例对象赋值给 instance$delegate

  • 当该属性被调用,即其 getInstance() 方法被调用时返回 ** FakeLazyKt.getValue(thisRef, property)** ,而这个方法的返回结果是对象 instance$delegate 内部的 _value 属性值,在 getValue() 第一次被调用时会将 _value 进行初始化,往后都是直接将 _value 的值返回,从而实现属性值的唯一一次初始化。

Observable

实现

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// 对外提供 observable 👀 函数
inline fun <T> observable(
initialValue: T,
crossinline onChange: (
property: KProperty<*>,
oldValue: T,
newValue: T
) -> Unit
): WriteReadProperty<Any?, T> = object : ObservableProperty<Any?, T>(initialValue) {
override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) {
onChange(property, oldValue, newValue)
}
}

inline fun <T> negative(
initialValue: T,
crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Boolean
): WriteReadProperty<Any?, T> = object : ObservableProperty<Any?, T>(initialValue) {
// 重写 beforeChange 方法,自定义逻辑
override fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean {
return onChange(property, oldValue, newValue)
}
}

// 读/写属性,委托的定义
interface WriteReadProperty<in R, T> {
operator fun getValue(thisRef: R, property: KProperty<*>): T
operator fun setValue(thisRef: R, property: KProperty<*>, value: T)
}

// 可观察的属性 WriteReadProperty 的一个实现类
abstract class ObservableProperty<in R, T>(initialValue: T) : WriteReadProperty<R, T> {

// 开始为外部传入的初始值 initialValue
private var value = initialValue

// value 改变前
open fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = true

// value 改变后
abstract fun afterChange(property: KProperty<*>, oldValue: T, newValue: T)

// 实现 getValue,直接返回 value
override fun getValue(thisRef: R, property: KProperty<*>): T {
return value
}

// 实现 setValue,如果符合 beforeChange 要求,
// 则更新 value 并回调 afterChange
override fun setValue(thisRef: R, property: KProperty<*>, value: T) {
val oldValue = this.value
if (!beforeChange(property, oldValue, value)) return
this.value = value
afterChange(property, oldValue, value)
}

}

使用

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
class Observable {

var name by observable("Plain") { property,
oldValue,
newValue ->
println("oldValue: $oldValue , newValue: $newValue")
}

var age by negative(10) { property,
oldValue,
newValue ->
return@negative oldValue != newValue
}

fun work() {
println(name)
name = "Dev"
println(name)

println("$age")
age = 10
println("$age")

}

}

✅ 运行结果

1
2
3
4
5
Plain
oldValue: Plain , newValue: Dev
Dev
10
10

NotNull

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
inline fun <reified T> notNull(): WriteReadProperty<Any?, T> = NotNullProperty()

class NotNullProperty<in R, T> : WriteReadProperty<R, T> {

private var value: T? = null

override fun getValue(thisRef: R, property: KProperty<*>): T {
if (value == null) throw IllegalStateException("属性 ${property.name} 应在获取之间初始化!")
return value!!
}

override fun setValue(thisRef: R, property: KProperty<*>, value: T) {
this.value = value
}

}

使用

1
2
3
4
5
6
7
8
9
10
class NotNull {

var name by notNull<String>()

fun work() {
// java.lang.IllegalStateException: 属性 name 应在获取之间初始化!
println(name)
}

}

参考文章

委托属性

示例地址

https://gitee.com/plain-dev/KotlinDelegationSample

本文作者 : Plain
This blog is under a CC BY-NC-SA 3.0 Unported License
本文链接 : https://plain-dev.com/kotlin-Implement-delegation-by-yourself/

本文最后更新于 天前,文中所描述的信息可能已发生改变