关于kotlin中的by关键字的用法,kotlin官方文档属性委托这一节讲得很清楚。
简单来说就是这样的,假设存在一个接口Component如下:
interface Component {
fun method1(): IntArray
fun method2(a: Int)
fun method3(a: Int, str: String)
}
那么对于实现该接口的方法,可以这样:
class Decorator(private val component: Component): Component {
override fun method1(): IntArray = component.method1()
override fun method2(a: Int) = component.method2(a)
override fun method3(a: Int, str: String) = component.method3(a, str)
}
但也可以通过by关键字更简单地实现:
class Decorator(private val component: Component): Component by component
这两段代码功能一致。
于是我们便能利用这一功能来更方便地实现装饰器模式,现在我们来实现三个装饰器类,分别对Component的三个方法进行装饰。
interface Component {
fun method1(): IntArray
fun method2(a: Int)
fun method3(a: Int, str: String)
}
class Decorator1(
private val component: Component,
private inline val f0: ()->Unit = {},
private inline val f1: (arr: IntArray)->IntArray = {arr -> arr}
): Component by component {
override fun method1(): IntArray {
f0()
return f1(component.method1())
}
// 相当于自动实现了
// override fun method2(a: Int) = component.method2(a)
// override fun method3(a: Int, str: String) = component.method3(a, str)
}
class Decorator2(
private val component: Component,
private inline val f0: (Int)->Unit = {},
private inline val f1: (Int)->Unit = {}
): Component by component {
override fun method2(a: Int) {
f0(a)
component.method2(a)
f1(a)
}
// override fun method1(): IntArray = component.method1()
// override fun method3(a: Int, str: String) = component.method3(a, str)
}
class Decorator3(
private val component: Component,
private inline val f0: (Int, String)->Unit = {_, _ -> },
private inline val f1: (Int, String)->Unit = {_, _ -> }
): Component by component {
override fun method3(a: Int, str: String) {
f0(a, str)
component.method3(a, str)
f1(a, str)
}
// override fun method1(): IntArray = component.method1()
// override fun method2(a: Int) = component.method2(a)
}
在主函数中调用这三个装饰器。
fun main() {
val obj1 = object: Component{
override fun method1(): IntArray = IntArray(5){it * it}
override fun method2(a: Int) = println("a^2 is ${a * a}")
override fun method3(a: Int, str: String) = println("a is a, and str is \"$str\"")
}
val obj2 = object: Component{
override fun method1(): IntArray = IntArray(10){it}
override fun method2(a: Int) = println("a - 3 is ${a - 3}")
override fun method3(a: Int, str: String) = println("say \"$str\" to number a = $a")
}
val dcrt1: Component = Decorator1(obj1, {}){ arr ->
println("old arr is ${arr.contentToString()}")
return@Decorator1 IntArray(10) {it * it *it}
}
val dcrt2: Component = Decorator2(obj1){ a ->
println("a is $a")
}
val dcrt3: Component = Decorator3(obj2, { a, str ->
println("say \"$str\" to java $a times")
}, {a, str ->
println("and say \"$str\" to kotlin $a times")
})
val dcrt4: Component = Decorator2(Decorator3(obj2){ a, str ->
println("say \"$str\" to jetBrains $a times")
}){a ->
println("a + 3 is ${a + 3}")
}
display(dcrt1, 10, "Hello world!")
display(dcrt2, 15, "Hello kotlin!")
display(dcrt3, 20, "Hello, java!")
display(dcrt4, 25, "Hello, jetBrains!")
}
fun display(component: Component, a: Int, str: String) {
with(component) {
println("--------------------------------")
println(method1().contentToString())
method2(a)
method3(a, str)
println("--------------------------------")
println()
}
}
运行结果: