kotlin小悟-这个继承有点不一样
Posted 林克在思考
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kotlin小悟-这个继承有点不一样相关的知识,希望对你有一定的参考价值。
今天聊聊kotlin中关于构造函数的一个话题。
我们知道,在kotlin中构造函数分为主构造函数和从构造函数,关于详细的内容,可以点击下面的文章链接了解。
Kotlin系列之主构造方法和初始化语句块
Kotlin系列之从构造方法
前置知识
我们经常会写这样的代码:
//父类
open class Father
// 子类
class Son: Father()
注意到子类在继承父类时,Father 后面的 () 了吗,这里表示父类的主构造函数,而且这个 () 不能少,因为子类的代码完整的写法是下面这样的:
class Son public constructor(): Father()
public作为构造函数的权限修饰符这个自然不用多说,后面紧跟的 constructor() 表示 Son 这个类的主构造函数。
所以上面的代码连起来可以理解为子类 Son 的主构造函数需要调用父类 Father 的主构造函数。这样你就知道了Father后面的括号是不能少的。
其实Java里面也是这样的规则,只是Java里面不分主构造函数和次构造函数。
现象
下面我们看一个现象:
// 父类
open class Father
// 子类
class Son: Father
constructor()
你会发现,这时候子类继承了 Father,但是Father后面的 () 没有了。
与此同时,Son类中多了一个次构造函数。也就是说,在继承自某个类时,有时候父类后面的 () 是不写的,而且写了会报错。
揭开谜底
如果你Java基础扎实,应该可以猜出几分原因,下面就来解释一下上面这种现象。
首先,我们明确一点,在kotlin中,在声明类的同时书写的构造函数,被我们称为主构造函数,写在类内部的构造函数被我们称为次构造函数。
就像最开始演示的那样,我们经常会把下面的代码简写:
// 完整形式
class Son public constructor(): Father()
// 简写形式
class Son: Father()
简写的形式,没有写出主构造函数的声明,所以kotlin就像Java一样,会在编译时帮我们补一个无参的主构造函数上去。
但是,一旦我们在类内部声明了一个无参的次构造函数,就像下面这样:
class Son: Father
constructor()
这样kotlin就不会再为我们补无参的主构造函数上去了,这时候Son这个类,就没有了主构造函数。
在原来我们这么做之前,语义是子类的主构造函数,需要调用父类的主构造函数,所以我们需要在Father后面加上括号,
现在子类没有主构造函数了,自然就不需要在声明时调用父类的主构造函数了,Father后面就不需要写括号了,只需要写Father来表明这是一种继承关系即可。
这就引出了另一个问题,这样写,那是不是子类的次构造函数就没法调用父类的主构造函数了。在Java里面子类的构造函数时一定要调用父类的构造函数的。难道在kotlin中不一样吗?
我们可以通过命令反编译生成的Son.class文件一探究竟。先切换到Son.class所在目录,并使用如下命令进行反编译:
cd out/production/Sample/
javap -c Son
反编译结果如下:
Compiled from "Son.kt"
public final class Son extends Father
public Son();
Code:
0: aload_0
1: invokespecial #8 // Method Father."<init>":()V
4: return
你可以很清楚地看到,最终还是会在编译时帮我们补上调用父类构造函数的代码的。
写在最后
其实kotlin跟Java有很多相似的地方,理解了Java,kotlin可以看作是Java的高级语法糖,但万变不离其宗。
以上是关于kotlin小悟-这个继承有点不一样的主要内容,如果未能解决你的问题,请参考以下文章