Kotlin 类补充篇之inline 和委托
文章目录
- Kotlin 类补充篇之inline 和委托
-
- 正文
-
- 内联类
-
- 1. inline 修饰类
- 2. inline 类的成员
- 标准委托
-
- 1. 延迟属性 Lazy
- 2. 观察委托 Observable
- 3. 属性映射到map
正文
内联类
- 内联类意味着类的数据会被“内联”到该类使用的地方
- 适用于业务逻辑需要用到某种类型的包装器,但是不想有额外的堆内存分配
1. inline 修饰类
inline class Password(val value: String)
//使用
// 不存在 'Password' 类的真实实例对象
// 将字符串内联到变量 securePassword
val securePassword = Password("Don't try this in production")
2. inline 类的成员
inline class Name(val s: String) {
val length: Int
get() = s.length
}
//使用
fun main() {
val name = Name("Kotlin")
println(name.length) // 属性的 get 方法会作为一个静态方法被调用
标准委托
1. 延迟属性 Lazy
-
lazy 接受一个 lambda 表达式并返回一个 Lazy 实例函数,返回的实例可以作为委托
-. 第一个 get 会执行表达式,后续调用 get 只是返回缓存
//小例子
val lazyValue: String by lazy {
println("computed!")
"Hello"
}
fun main() {
println(lazyValue)
println(lazyValue)
}
- lazy 调用 get 方法使用同步锁
//核心代码在 SynchronizedLazyImpl 里
private class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable {
private var initializer: (() -> T)? = initializer
//默认值
@Volatile private var _value: Any? = UNINITIALIZED_VALUE
// get 方法的同步锁
private val lock = lock ?: this
//get 方法
override val value: T
get() {
val _v1 = _value
//缓存在 value
if (_v1 !== UNINITIALIZED_VALUE) {
@Suppress("UNCHECKED_CAST")
return _v1 as T
}
return synchronized(lock) {
val _v2 = _value
if (_v2 !== UNINITIALIZED_VALUE) {
@Suppress("UNCHECKED_CAST") (_v2 as T)
} else {
//自行实现的 lambda 表达式
val typedValue = initializer!!()
_value = typedValue
initializer = null
typedValue
}
}
}
override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE}
2. 观察委托 Observable
观察委托会给你设置默认值,当委托属性被修改会调用你设置的 lambda 表达式
// 可观察属性
class User {
var name: String by Delegates.observable("initv") { property, oldValue, newValue ->
run {
println("oldValue: $oldValue, newValue: $newValue ")
}
}
}
private fun main(){
//输出
// initv
// oldValue: initv, newValue: f
// f
// oldValue: f, newValue: fuck
// fuck
val user = User()
println(user.name)
user.name = "f"
println(user.name)
user.name = "fuck"
println(user.name)
}
3. 属性映射到map
//属性委托给map 来映射, 使用于 json 或者 xml 解析成map
//还是 gson 好使,哈哈
class Boy(val map:Map<String, Any?>){
val name:String by map
val age:Int by map
}
private fun mapDelegateDemo(){
val boy = Boy(mapOf(
"name" to "John Doe",
"age" to 25))
println(boy.name)
println(boy.age)
}