【Android开发日志】Kotlin 面向对象编程 – 构造函数(13)

Kotlin的构造函数分为两种:主构造函数次构造函数

主构造函数

最常用的函数,每个类class都默认包含一个主构造函数,你也可以显式地给它指明参数。主构造函数的特点是没有fun这样的函数体,直接写在我们类的名称后面。两种写法如下:

class Student1: Human() {
    var number = ""
    var grade = 0
}

class Student2(val number: Number, val grade: String){
    
}

第二种写法:两参数为实例化时必须传入的参数,你在具体到哪个学生时必须同时提供学号年级

所以,我们不用之后再赋值,可以定义为val,实例化代码如下:

fun main(){
    val xiaoming = Student2(number = "0161120111", grade = 4)
    xiaoming.name = "小明"
    xiaoming.age = 22

    xiaoming.eat()
}

那么问题来了,我们单用主构造函数,如何完成一些逻辑,例如:吃东西。

这里我们使用init()就是一般用作初始化的那个函数,这个函数是默认运行的,不用调用。代码如下:

class Student2(val number: String, val grade: Number): Human(){
    init {
        println("学号是$number$grade 学生$name 正在吃饭,他已经$age 岁了。")
    }
}

我们看一下结果:

可以很明显看到:第一句打印,并没有姓名年龄。是在我们给nameage赋值之前,就已经运行了。

Kotlin在这里规定:若我们继承,子类必须调用父类的构造函数。

就像孩子一定要继承爸爸的某些特征,不可能有例外。

而我们继承时,父类后面的()就是指定了我们要继承父类的哪个构造函数。

这里你是造物主,你可以指定孩子要继承父亲的哪些特征。虽然我们什么都没有写,可父类默认包含一个主构造函数、子类也默认调用了这个主构造函数,只是它没有参数没有内容而已。

下面我们把父类加入有参的主构造函数,转至Human.kt,更改代码如下:

open class Human(name: String, age: Number) {
    init {
        println("$age$name 正在吃饭。")
    }
}

随后我们回到Student.kt,更改代码如下:

class Student(val number: String, val grade: Number,name: String, age: Number):
    Human(name,age){
    init {
        println("学号是$number$grade 学生$name 正在吃饭,他已经$age 岁了。")
    }
}

我们发现,Student里面我们定义了name,age,后面Human()里还有name,age

这里要注意,我们现在定义的Student类,继承Human父类时需要传入name,age两个参数。

所以我们需要在构建Student时定义nameage,在继承时才能传给Human值。

当然与父类定义重名时会冲突,所以这里没有valvar
下面我们来看示例代码:

package com.example.helloword

class Student(val number: String, val grade: Number,name: String, age: Number):
    Human(name,age){
    init {
        println("学号是$number$grade 学生$name 正在吃饭,他已经$age 岁了。")
    }
}

fun main(){
    val xiaoming = Student(number = "0161120111", grade = 4,name = "小明", age = 22)
}

运行结果如下:

次构造函数

其实我们实践中几乎用不到次构造函数,这里只做了解进行讲解。对于次构造函数,你需要了解以下内容:

  • 任何一个类只有一个主构造函数,可以有多个次构造函数
  • 次构造函数可以用于实例化一个类,此点与主构造函数相同。
  • 次构造函数必须调用主构造函数
  • 当一个类没有显式定义一个主构造函数,而显式定义了一个次构造函数,此类没有主构造函数
  • 次构造函数通过constructor定义

次构造函数像一个小跟班一样,跟着主构造函数完成相应的功能。

下面我们看代码:

package com.example.helloword

class Student(val number: String, val grade: Number,name: String, age: Number):
    Human(name,age){
    init {
        println("学号是$number$grade 年级学生$name 正在吃饭,他已经$age 岁了。")
    }
    constructor(name: String, age: Number):this("111111",0,name, age){

    }
    constructor():this("小明2", 22){

    }
}
  • 第一个次构造函数,传入nameage,并用this调用了了上面的主构造函数,numbergrade为写好的传入值,nameage是我们实例化时的传入值。
  • 第二个次构造函数,没有传入值,用this调用上面的第一个次构造函数(间接调用主构造函数),this后直接指定了nameage,因为第一个次构造函数传入值为nameage,而numbergrade则沿用第一个次构造函数的定义值。
fun main(){
    val student1 = Student()
    println("")
    val student2 = Student("小明3", 23)
    println("")
    val student3 = Student("222222", 4,"小明4", 24)
}

在主函数中,我们就有了三种实例化的格式,分别对应:

  • 第二个次构造函数
  • 第一个次构造函数
  • 主构造函数
    来看运行结果:

特殊情况

最后还有一种无主构造函数,有次构造函数情况。代码如下:

class Student:Human{
    constructor(name:String, age:Number):super(name, age){
        
    }
}

注意:

  • Student后面没有主构造函数(),因此Human后也不需要加()
  • 次构造函数直接调用父类构造函数
  • 所以Human后的括号不是必须的,需要看主构造函数

关于superthis在构造函数中使用方法:

  • super(参数):调用父类中的某一个构造函数。
  • this(参数):调用本类中另一种形式的构造函数。

构造函数是不是有点点难呢,大家好好消化一下。


欢迎关注小试编程
​​​​在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小试编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值