多种类型的键值对设计
多种类型的键值对设计
从源码看多种类型的键值对设计
ViewModel CreationExtras Key 设计
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public sealed class CreationExtras {
internal val map: MutableMap<Key<*>, Any?> = mutableMapOf()
/**
* Key for the elements of [CreationExtras]. [T] is a type of an element with this key.
*/
public interface Key<T>
/**
* Returns an element associated with the given [key]
*/
public abstract operator fun <T> get(key: Key<T>): T?
object Empty : CreationExtras() {
override fun <T> get(key: Key<T>): T? = null
}
}
Key
的泛型 T
代表对应 Value
的类型。相对于 Map<K,V>
,这种定义方式可以更加类型安全地获取多种类型的键值对,CoroutineContext
等也是采用这种设计。
CoroutineContext
多数据类型的键值对设计
一般
一个 MutableMap<K, Any?>
,要存储多种数据类型,Value
设计成 Any?
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
val map: MutableMap<String, Any?> = mutableMapOf()
// 存储不同类型的值
map["key1"] = 1
map["key2"] = "hacket"
map["key3"] = true
// 取出来,需要强制转换
val v1 = map["key1"] as Int
val v2 = map["key2"] as String
val v3 = map["key3"] as Boolean
// 或者
class NormalKvCache {
val map: MutableMap<String, Any?> = mutableMapOf()
fun put(key: String, v: Any?) {
map[key] = v
}
fun <T> get(key: String): T? {
return map[key] as T?
}
}
// 测试
val normalKvCache = NormalKvCache()
normalKvCache.put("k1", "hacket");
normalKvCache.put("k2", 2)
normalKvCache.put("k3", true)
val v1 = normalKvCache.get<String>("k1")
val v2 = normalKvCache.get<Int>("k2")
val v3 = normalKvCache.get<Boolean>("k3")
这种方式,取出来的值需要手动转换成存进去的类型,不够安全。
基于 Key<T>
设计
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
class MyKvCache {
internal val map: MutableMap<Key<*>, Any?> = mutableMapOf()
interface Key<T>
/**
* Associates the given [key] with [t]
*/
operator fun <T> set(key: Key<T>, t: T) {
map[key] = t
}
fun <T> get(key: Key<T>): T? {
@Suppress("UNCHECKED_CAST")
return map[key] as T?
}
companion object {
private object K1 : Key<String>
@JvmField
val KEY1: Key<String> = K1
private object K2 : Key<String>
@JvmField
val KEY2: Key<String> = K2
private object K3 : Key<Int>
@JvmField
val KEY3: Key<Int> = K3
private object K4 : Key<Boolean>
@JvmField
val KEY4: Key<Boolean> = K4
}
}
测试:
1
2
3
4
5
6
7
8
9
10
11
12
13
fun test1() {
val myKvCache = MyKvCache()
myKvCache[MyKvCache.KEY1] = "hacket1"
myKvCache[MyKvCache.KEY2] = "hacket2"
myKvCache[MyKvCache.KEY3] = 11
myKvCache[MyKvCache.KEY4] = true
val v1 = myKvCache.get(MyKvCache.KEY1)
val v2 = myKvCache.get(MyKvCache.KEY2)
val v3 = myKvCache.get(MyKvCache.KEY3)
val v4 = myKvCache.get(MyKvCache.KEY4)
println("v1=$v1, v2=$v2, v3=$v3, v4=$v4")
}
本文由作者按照 CC BY 4.0 进行授权