导言
在Kotlin中,by
关键字首要用于完成托付形式。托付形式是一种设计形式,它答应一个目标将部分职责托付给另一个目标。在Kotlin中,by
关键字供给了一种简练的语法,使得托付的完成变得愈加轻松。
托付形式概述
在托付形式中,有两个首要人物:
- 托付类(Delegated Class): 持有实践的作业目标,担任将部分职责托付给这个目标。
-
托付特点(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
方法被托付给了 DefaultPrinter
的 print
方法。
自界说托付类
除了运用接口作为托付的目标外,咱们还可以自界说托付类。自界说托付类需求完成特点托付的接口,即具备 getValue
和 setValue
方法。以下是一个简略的自界说托付类的比如:
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
类完成了特点托付的接口,经过重写 getValue
和 setValue
方法完成了特点的读取和设置。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: 每日一算法,由浅入深,欢迎参加一同共勉。