导言

在Kotlin中,by 关键字首要用于完成托付形式。托付形式是一种设计形式,它答应一个目标将部分职责托付给另一个目标。在Kotlin中,by 关键字供给了一种简练的语法,使得托付的完成变得愈加轻松。

托付形式概述

在托付形式中,有两个首要人物:

  1. 托付类(Delegated Class): 持有实践的作业目标,担任将部分职责托付给这个目标。
  2. 托付特点(Delegated Property): 在托付类中声明的特点,运用 by 关键字将其托付给其他类。

by关键字的作业原理

当运用 by 关键字将特点托付给其他类时,编译器会在后台生成一些额定的代码,实践上是将特点的 getter 和 setter 方法托付给特定的托付类。下面是一个简略的比如来说明 by 关键字的作业原理:

interface Printer {
    fun print(message: String)
}
class DefaultPrinter : Printer {
    override fun print(message: String) {
        println("Default: $message")
    }
}
class CustomPrinter(private val delegate: Printer) : Printer by delegate
fun main() {
    val customPrinter = CustomPrinter(DefaultPrinter())
    customPrinter.print("Hello, Kotlin!")
}

在这个比如中,CustomPrinter 类经过 by 关键字将 Printer 接口的完成托付给了 DefaultPrinter 类。编译器会生成相似下面的代码:

class CustomPrinter(private val delegate: Printer) : Printer {
    override fun print(message: String) {
        delegate.print(message)
    }
}

实践上,CustomPrinter 中的 print 方法被托付给了 DefaultPrinterprint 方法。

自界说托付类

除了运用接口作为托付的目标外,咱们还可以自界说托付类。自界说托付类需求完成特点托付的接口,即具备 getValuesetValue 方法。以下是一个简略的自界说托付类的比如:

import kotlin.reflect.KProperty
class CustomDelegate {
    private var value: String = ""
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        println("Getting value: $value")
        return value
    }
    operator fun setValue(thisRef: Any?, property: KProperty<*>, newValue: String) {
        println("Setting value: $newValue")
        value = newValue
    }
}
class Example {
    var customProperty: String by CustomDelegate()
}
fun main() {
    val example = Example()
    example.customProperty = "Hello, Kotlin!"
    println(example.customProperty)
}

在上面的比如中,CustomDelegate 类完成了特点托付的接口,经过重写 getValuesetValue 方法完成了特点的读取和设置。Example 类中的 customProperty 特点经过 by 关键字托付给了 CustomDelegate 类。

lazy原理

有了上面的根底,再来看lazy的完成就非常简略。

lazy 是 Kotlin 标准库中的一个函数,用于完成延迟初始化。它的首要作用是将一个 lambda 表达式作为参数传递给 lazy 函数,该 lambda 表达式将在初次拜访特点时履行,并且只会履行一次。lazy 回来一个 Lazy 类型的实例,该实例包括一个被托付的特点,以及相应的初始化逻辑。

以下是 lazy 的简化完成原理,为了更好地了解,咱们将选用伪代码的形式:

class Lazy<T>(private val initializer: () -> T) {
    private var value: T? = null
    private var isInitialized: Boolean = false
    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        if (!isInitialized) {
            value = initializer()
            isInitialized = true
        }
        return value!!
    }
}
fun <T> lazy(initializer: () -> T): Lazy<T> = Lazy(initializer)

上述代码中,咱们界说了一个 Lazy 类,它承受一个 lambda 表达式 initializer,这个 lambda 表达式包括了特点初次拜访时的初始化逻辑。Lazy 类包括一个泛型参数 T,表明被托付的特点的类型。

  • value 存储被托付特点的值,初始值为 null。
  • isInitialized 用于追寻特点是否现已被初始化。

Lazy 类还完成了 getValue 操作符函数,这是特点托付的关键。当被托付的特点初次被拜访时,getValue 函数会履行 initializer lambda 表达式,初始化特点的值,并将 isInitialized 设置为 true。之后,再次拜访该特点时,直接回来现已初始化过的值。

最终,咱们经过 lazy 函数创建了一个 Lazy 类的实例,用于实践的特点托付。在实践运用中,lazy 函数可以直接作为特点的托付,如下所示:

val myProperty: String by lazy {
    println("Initializing myProperty")
    "Hello, Kotlin!"
}
fun main() {
    println(myProperty) // 第一次拜访,会履行初始化逻辑
    println(myProperty) // 后续拜访,直接回来已初始化的值
}

在上述比如中,myProperty 的初始化逻辑只在初次拜访时履行,之后的拜访直接回来现已初始化的值。

总结

经过 by 关键字,Kotlin 供给了一种优雅而强大的托付形式完成方式。无论是经过接口还是自界说托付类,都可以轻松地完成代码的重用和解耦。了解 by 关键字的完成原理有助于更深化地了解 Kotlin 的托付形式,并在实践开发中愈加灵敏地运用。

引荐

android_startup: 供给一种在使用发动时可以愈加简略、高效的方式来初始化组件,优化发动速度。不仅支撑Jetpack App Startup的悉数功能,还供给额定的同步与异步等待、线程操控与多进程支撑等功能。

AwesomeGithub: 根据Github的客户端,纯练习项目,支撑组件化开发,支撑账户暗码与认证登陆。运用Kotlin言语进行开发,项目架构是根据JetPack&DataBinding的MVVM;项目中运用了Arouter、Retrofit、Coroutine、Glide、Dagger与Hilt等盛行开源技术。

flutter_github: 根据Flutter的跨渠道版别Github客户端,与AwesomeGithub相对应。

android-api-analysis: 结合详细的Demo来全面解析Android相关的知识点, 帮助读者可以更快的掌握与了解所论述的关键。

daily_algorithm: 每日一算法,由浅入深,欢迎参加一同共勉。