Kotlin 核心编程 (54):面向对象 3.3.3

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

Kotlin核心编程(54):面向对象 3.3.3

(内部类解决多继承问题的方案)

内容简介
本书不是一本简单介绍 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 响应式框架和编程等内容。

我们要探讨的第 2 种方式就是用内部类模拟多继承的效果。我们知道,在 Java 中可以将一个类的定义放在另一个类的定义内部,这就是内部类。由于内部类可以继承一个与外部类无关的类,所以这保证了内部类的独立性,我们可以用它的这个特性来尝试解决多继承的问题。

在探讨这个问题之前,我们有必要来了解一下 Kotlin 中内部类的语法。如你所知,Java 的内部类定义非常直观,我们只要在一个类内部再定义一个类,那么这个类就是内部类了,如:

复制代码
public class OuterJava {
private String name = "This is Java's inner class syntax.";
class InnerJava { // 内部类
public void printName()
{
System.out.println(name);
}
}
}

现在我们尝试用类似的 Kotlin 代码来改写这段代码,看看有没有类似的效果。

复制代码
class OuterKotlin {
val name = "This is not Kotlin's inner class syntax."
class ErrorInnerKotlin { // 其实是嵌套类
fun printName() {
print("the name is $name") //error
}
}
}
// 运行结果
Error:(5, 32) Unresolved reference: name

怎么回事,这段代码竟然报错了?其实这里闹了乌龙,当前我们声明的并不是 Kotlin 中的内部类,而是嵌套类的语法。如果要在 Kotlin 中声明一个内部类,我们必须在这个类前面加一个 inner 关键字,就像这样子:

复制代码
class OuterKotlin {
val name = "This is truely Kotlin's inner class syntax."
inner class InnerKotlin {
fun printName() {
print("the name is $name")
}
}
}

内部类 vs 嵌套类
众所周知,在 Java 中,我们通过在内部类的语法上增加一个 static 关键词,把它变成一个嵌套类。然而,Kotlin 则是相反的思路,默认是一个嵌套类,必须加上 inner 关键字才是一个内部类,也就是说可以把静态的内部类看成嵌套类。
内部类和嵌套类有明显的差别,具体体现在:内部类包含着对其外部类实例的引用,在内部类中我们可以使用外部类中的属性,比如上面例子中的 name 属性;而嵌套类不包含对其外部类实例的引用,所以它无法调用其外部类的属性。

好了,在熟悉了内部类的语法之后,我们就回到之前的骡子的例子,然后用内部类来改写它。

复制代码
open class Horse { // 马
fun runFast() {
println("I can run fast")
}
}
open class Donkey { // 驴
fun doLongTimeThing() {
println("I can do some thing long time")
}
}
class Mule { // 骡子
fun runFast() {
HorseC().runFast()
}
fun doLongTimeThing() {
DonkeyC().doLongTimeThing()
}
private inner class HorseC : Horse()
private inner class DonkeyC : Donkey()
}

通过这个修改后的例子可以发现:

1)我们可以在一个类内部定义多个内部类,每个内部类的实例都有自己的独立状态,它们与外部对象的信息相互独立;

2)通过让内部类 HorseC、DonkeyC 分别继承 Horse 和 Donkey 这两个外部类,我们就可以在 Mule 类中定义它们的实例对象,从而获得了 Horse 和 Donkey 两者不同的状态和行为;

3)我们可以利用 private 修饰内部类,使得其他类都不能访问内部类,具有非常良好的封装性。

因此,可以说在某些场合下,内部类确实是一种解决多继承非常好的思路。

Kotlin核心编程(54):面向对象 3.3.3

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

评论

发布