kotlin 委托
在 Kotlin 中,委托(Delegation)是一种设计模式,可以简化代码,并且通过复用现有类的功能来实现新的行为。Kotlin 提供了几种形式的委托:类委托、委托属性等。以下是对这两种委托方式的详细介绍:
类委托
类委托是 Kotlin 中的一项特性,允许一个类将接口中定义的方法实现委托给另一个对象。使用 by
关键字可以很容易地实现类委托。
示例:
interface Speaker {
fun speak()
}
class Person(val name: String) : Speaker {
override fun speak() {
println("Hello, my name is $name.")
}
}
class Robot(val model: String) : Speaker {
override fun speak() {
println("Hi, I am a robot, model $model.")
}
}
class CommunicationDevice(speaker: Speaker) : Speaker by speaker
fun main() {
val john = Person("John")
val robot = Robot("RX-78")
val device1 = CommunicationDevice(john)
val device2 = CommunicationDevice(robot)
device1.speak() // 输出: Hello, my name is John.
device2.speak() // 输出: Hi, I am a robot, model RX-78.
}
在这个例子中,CommunicationDevice
类通过 by speaker
将 Speaker
接口的方法实现委托给传入的 speaker
对象。
属性委托
属性委托是另一个强大的 Kotlin 特性,允许将属性的存储和访问行为交给另外一个对象来处理。最常用的属性委托是 lazy
和 observable
。
示例:lazy
lazy
是一个由 Kotlin 标准库提供的属性委托,适用于惰性初始化,即属性只在第一次访问时才会计算其值。
val lazyValue: String by lazy {
println("Computed!")
"Hello"
}
fun main() {
println(lazyValue) // 输出: Computed!\nHello
println(lazyValue) // 输出: Hello
}
示例:observable
observable
委托允许我们在值被改变时执行某些操作,比如监听属性的变化。
import kotlin.properties.Delegates
var observedValue: String by Delegates.observable("<no value>") { prop, old, new ->
println("$old -> $new")
}
fun main() {
observedValue = "First"
// 输出: <no value> -> First
observedValue = "Second"
// 输出: First -> Second
}
自定义属性委托
我们还可以通过实现 ReadOnlyProperty
或 ReadWriteProperty
接口来自定义属性委托。
示例:自定义委托
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
class NonNegativeVar(initialValue: Int) : ReadWriteProperty<Any?, Int> {
private var value = initialValue
override fun getValue(thisRef: Any?, property: KProperty<*>): Int = value
override fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
if (value >= 0) {
this.value = value
} else {
throw IllegalArgumentException("Negative value is not allowed")
}
}
}
var nonNegativeInt: Int by NonNegativeVar(0)
fun main() {
nonNegativeInt = 5
println(nonNegativeInt) // 输出: 5
try {
nonNegativeInt = -1
} catch (e: IllegalArgumentException) {
println(e.message) // 输出: Negative value is not allowed
}
}
通过这种方式,我们可以在类和属性级别利用委托模式,来增强和复用代码功能。Kotlin 的委托特性提供了强大的灵活性和可复用性,非常适合现代软件开发。