《Kotlin核心编程》 ——3.3.4 使用委托代替多继承

举报
华章计算机 发表于 2020/02/21 22:50:39 2020/02/21
【摘要】 本节书摘来自华章计算机《Kotlin核心编程》 —— 书中第3章,第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的能力,更加直观,虽然背后也是通过委托对象来执行具体的方法逻辑的。


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。