天天看点

Kotlin 类补充篇之inline 和委托Kotlin 类补充篇之inline 和委托

Kotlin 类补充篇之inline 和委托

文章目录

  • Kotlin 类补充篇之inline 和委托
    • 正文
      • 内联类
        • 1. inline 修饰类
        • 2. inline 类的成员
      • 标准委托
        • 1. 延迟属性 Lazy
        • 2. 观察委托 Observable
        • 3. 属性映射到map

正文

内联类

  1. 内联类意味着类的数据会被“内联”到该类使用的地方
  2. 适用于业务逻辑需要用到某种类型的包装器,但是不想有额外的堆内存分配

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)
}