《Kotlin核心编程》 ——3.3.3 内部类解决多继承问题的方案
3.3.3 内部类解决多继承问题的方案
我们要探讨的第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修饰内部类,使得其他类都不能访问内部类,具有非常良好的封装性。
因此,可以说在某些场合下,内部类确实是一种解决多继承非常好的思路。
- 点赞
- 收藏
- 关注作者
评论(0)