kotlin小悟-这个继承有点不一样(代码片段)

林克在思考 林克在思考     2023-02-21     681

关键词:

今天聊聊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小悟-安全调用符(代码片段)

今天看看kotlin中的安全调用符的一个注意点。之前的文章已经讲过kotlin中的安全调用符,可以点击查看。知识点kotlin中的安全调用符?.是线程安全的。代码验证我们打开IDEA写下面一段代码:classSample(varname:String?)funtest()if(n... 查看详情

kotlin小悟-安全调用符(代码片段)

今天看看kotlin中的安全调用符的一个注意点。之前的文章已经讲过kotlin中的安全调用符,可以点击查看。知识点kotlin中的安全调用符?.是线程安全的。代码验证我们打开IDEA写下面一段代码:classSample(varname:String?)funtest()if(n... 查看详情

kotlin学习之路:继承(代码片段)

...承二.继承中的构造函数2.1继承中Java的构造函数2.2继承中Kotlin的构造函数2.3Kotlin多个构造函数的情况三.重写和重载3.1方法的重写3.2属性的重写四.super关键字4.1简单用法4.2复杂情况下的用法4.2.1子类重写方法中使用super4.2.2子类选择... 查看详情

kotlin学习笔记之面向对象(代码片段)

...ff0c;使用interface表示,示例代码:与java一样,kotlin定义类时要遵循单继承多实现的原则(即只能继承一个父类,可以实现多个接口)kotlin中定义的类和方法默认都是final的,不可重写,如果要实现重... 查看详情

kotlin语言中的继承与构造函数(详解)(代码片段)

        学习kotlin时,有很多小伙伴无法理解为何有的继承结构父类后面需要加括号,有时候却不用加括号,本篇文章小编将为你们解除这个困惑!顺便为大家详解一下kotlin中的主构造函数和次构造函数。   ... 查看详情

kotlin快速入门:基础语法类与继承集合(代码片段)

参考书籍:《AtomicKotlin》,全英文,读起来慢,但是写得很详细,没有任何语言基础的也能看懂《第一行代码Android第三版》,第二章,有java基础的看一看就会了Kotlin中文文档,很详细,可以当... 查看详情

kotlin快速入门:基础语法类与继承集合(代码片段)

参考书籍:《AtomicKotlin》,全英文,读起来慢,但是写得很详细,没有任何语言基础的也能看懂《第一行代码Android第三版》,第二章,有java基础的看一看就会了Kotlin中文文档,很详细,可以当... 查看详情

kotlin入门(代码片段)

...数:123valinvoice=Invoice() valcustomer=Customer("JoeSmith")注意Kotlin并没有 new 关键字。 继承在Kotlin中所有类都有 查看详情

kotlin类属性方法继承多态(代码片段)

Kotlin类、属性、方法、继承、多态一、Kotlin类1.kotlin定义类使用open修饰类,表明可被子类继承使用open修饰属性,表明可被子类覆写/***Kotlin使用class定义类Phone,使用open修饰类,表明可被继承*主构造器参数为system... 查看详情

kotlin接口(代码片段)

来源于菜鸟教程Kotlin接口与Java8类似,使用interface关键字定义接口。允许方法有默认实现:interfaceMyInterfacefunbar()//未实现funfoo()//已实现println("foo")实现接口一个类或者对象可以实现一个或多个接口。classChild:MyInterfaceoverridefunbar()//... 查看详情

kotlin学习笔记之面向对象(代码片段)

...ff0c;使用interface表示,示例代码:与java一样,kotlin定义类时要遵循单继承多实现的原则(即只能继承一个父类,可以实现多个接口)kotlin中定义的类和方法默认都是final的,不可重写,如果要实现重... 查看详情

kotlin基础类(代码片段)

定义一个可以被继承的类:open关键字属性列表:constructoropenclassBaseDaoconstructor(varsex:Boolean,varname:String)//类ADao继承了BaseDao类,可以选择是否设置默认值//有默认值的情况下,可以不传参数classADao(sex:Boolean=false,name:St 查看详情

深入kotlin-接口和抽象类(代码片段)

...拥有方法实现(default关键字修饰的接口方法)。Kotlin也是同样的:interfaceA funmethod() println("A") 如果一个类B继承了接口A,因为A中的方法已经有默认实现,则B不需要实现接口A:classB:A重写接口方法如果需... 查看详情

类对象和接口(代码片段)

1、定义类继承结构1.1kotlin中的接口声明接口interfaceClickablefunclick()声明了一个只有一个抽象方法的接口,和java中一样,实现这个接口的类要提供这个抽象方法的具体实现。实现接口classButton:Clickableoverridefunclick()=println("Iwasclick... 查看详情

swiftswot的扩展就像kotlin一样(代码片段)

查看详情

kotlin中抽象类(代码片段)

抽象类和接口很类似,抽象类不能被实例化需要使用abstract关键字声明,抽象类实现接口后,接口中没有函数体的函数可以不重写,接口中的这些方法就自动被继承到实现接口的抽象类中,称为抽象方法packageloaderman.demoopenclassbase... 查看详情

kotlin开发基础(代码片段)

...一时间获取我的最新文章,请关注公众号:技术特工队Kotlin开发基础(一)Kotlin开发基础(二)Kotlin开发基础(三)类本篇文章主要介绍类的继承,接口,复写,单例,以及object属性的介... 查看详情

kotlin-类和对象(代码片段)

...写属性重写初始化顺序抽象类接口类概述和Java一样,Kotlin中的类由class关键字修饰,比如:classPerson但是不同的是,如果Kotlin的类是空的,即不含任何属性或方法,花括号是可以省略的:classEmptyJava的祖... 查看详情