Kotlin 核心编程 (55):面向对象 3.3.4

阅读数:2 2019 年 12 月 28 日 22:25

Kotlin核心编程(55):面向对象 3.3.4

(使用委托代替多继承)

内容简介
本书不是一本简单介绍 Kotlin 语法应用的图书,而是一部专注于帮助读者深入理解 Kotlin 的设计理念,指导读者实现 Kotlin 高层次开发的实战型著作。书中深入介绍了 Kotlin 的核心语言特性、设计模式、函数式编程、异步开发等内容,并以 Android 和 Web 两个平台为背景,演示了 Kotlin 的实战应用。
全书共 13 章,分为 4 个部分:
热身篇—Kotlin 基础(第 1~2 章),简单介绍了 Kotlin 设计哲学、生态及基础语法,其中包括 Kotlin 与 Scala、Java 之间的关联与对比,以及 Kotlin 的类型声明的特殊性、val 和 var 的使用、高阶函数的使用、面向表达式编程的使用、字符串的定义与操作等内容;
下水篇—Kotlin 核心(第 3~8 章),深入介绍了面向对象、代数数据类型、模式匹配、类型系统、Lambda、集合、多态、扩展、元编程等 Kotlin 开发核心知识,这是本书的重点,其中涉及很多开发者特别关心的问题,比如多继承问题、模式匹配问题、用代数数据类型抽象业务问题、泛型问题、反射问题等。
潜入篇—Kotlin 探索(第 9~11 章),探索 Kotlin 在设计模式、函数式编程、异步和并发等编程领域的应用,其中包括对 4 大类设计模式、Typeclass 实现、函数式通用结构设计、类型替代异常处理、共享资源控制、CQRS 架构等重点内容的深入剖析;
遨游篇—Kotlin 实战(第 12~13 章),着重演示了 Kotlin 在 Android 和 Web 平台的实战案例,其中涉及架构方式、单向数据流模型、解耦视图导航、响应式编程、Spring 5 响应式框架和编程等内容。

在看完与 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 的能力,更加直观,虽然背后也是通过委托对象来执行具体的方法逻辑的。

Kotlin核心编程(55):面向对象 3.3.4

购书地址 https://item.jd.com/12519581.html?dist=jd

评论

发布