《Kotlin核心编程》 ——3.3.4 使用委托代替多继承
3.3.4 使用委托代替多继承
在看完与Java类似的多继承解决思路后,我们再来看一种Kotlin中新引入的语法—委托。通过它我们也可以代替多继承来解决类似的问题。
关于委托,可能你会很熟悉。比如你非常了解委托模式,或者你是一名C#开发者,熟悉其中的delegate关键字。简单来说,委托是一种特殊的类型,用于方法事件委托,比如你调用A类的methodA方法,其实背后是B类的methodA去执行。
印象中,要实现委托并不是一件非常自然直观的事情。但庆幸的是,Kotlin简化了这种语法,我们只需通过by关键字就可以实现委托的效果。比如我们之前提过的by lazy语法,其实就是利用委托实现的延迟初始化语法。我们再来重新回顾一下它的使用:
val laziness: String by lazy {
// 用by lazy实现延迟初始化效果
println("I will have a value")
"I am a lazy-initialized string"
}
委托除了延迟属性这种内置行为外,还提供了一种可观察属性的行为,这与我们平常所说的观察者模式很类似。观察者模式在Android开发中应用很广,我们会利用委托在第9章中介绍它如何改善Android中的观察者模式。
接下来,我们来看看如何通过委托来代替多继承实现需求。请看下面的例子:
interface CanFly {
fun fly()
}
interface CanEat {
fun eat()
}
open class Flyer : CanFly {
override fun fly() {
println("I can fly")
}
}
open class Animal : CanEat {
override fun eat() {
println("I can eat")
}
}
class Bird(flyer: Flyer, animal: Animal) : CanFly by flyer, CanEat by animal {}
fun main(args: Array<String>) {
val flyer = Flyer()
val animal = Animal()
val b = Bird(flyer, animal)
b.fly()
b.eat()
}
有人可能会有疑问:首先,委托方式怎么跟接口实现多继承如此相似,而且好像也并没有简单多少;其次,这种方式好像跟组合也很像,那么它到底有什么优势呢?主要有以下两点:
1)前面说到接口是无状态的,所以即使它提供了默认方法实现也是很简单的,不能实现复杂的逻辑,也不推荐在接口中实现复杂的方法逻辑。我们可以利用上面委托的这种方式,虽然它也是接口委托,但它是用一个具体的类去实现方法逻辑,可以拥有更强大的能力。
2)假设我们需要继承的类是A,委托对象是B、C、我们在具体调用的时候并不是像组合一样A.B.method,而是可以直接调用A.method,这更能表达A拥有该method的能力,更加直观,虽然背后也是通过委托对象来执行具体的方法逻辑的。
- 点赞
- 收藏
- 关注作者
评论(0)