【第四阶段】kotlin语言的构造函数学习

1.主构造函数

package Kotlin.Stage4
//主构造函数,规范来说,都是增加_xxx的形式,临时的输入类型,不能直接用。需要接收下来,成为变量才能用。
class TestBase(_name:String,_sex:Char,_age:Int,_info:String){   //主构造函数
      var name=_name
      get() = field //get不允许私有化
      private set(value) {  //私有化的set在调用时 不能访问,无法set
          field=value
      }

    val sex=_sex
    get() = field
    //set(value){}  由于是只读val的 因此无法使用set函数

    var age=_age
    get() = field +1

    var info=_info
    get() = "【$field】"

    fun show(){
        //println(_name) _name临时输入类型 不能直接用,需要接收才能用
        println(name)
        println(sex)
        println(age)
        println(info)
    }
}

fun main() {
    //创建对象
    var p=TestBase(_name = "kotlin",_age = 20,_sex = '男',_info = "我是语言")
    p.show()
}

执行结果
在这里插入图片描述
类似java中的this.nam=name

2.主构造函数里面定义属性

优化上述构造,一步到位

package Kotlin.Stage4

class TestBase1(var name:String,val sex:Char,var age:Int, var info:String){   //主构造函数

    fun show(){
        println(name)
        println(sex)
        println(age)
        println(info)
    }
}

fun main() {
    //创建对象
    var p=TestBase1(name = "kotlin",age = 20,sex = '男',info = "我是语言")
    p.show()
}

执行结果
在这里插入图片描述

3.次构造函数

constructor()
package Kotlin.Stage4
class TestBase3(name:String){ //主构造
     //次构造函数必须调用主构造,否在会报错。主构造统一管理,为了更好的初始化
    //2个参数的次构造
    constructor(name: String,sex:Char):this(name){
         println("2个参数的次构造函数:name=$name,sex=$sex")
     }
    constructor(name: String,sex: Char,age:Int):this(name){
        println("3个参数的次构造函数:name=$name,sex=$sex,age=$age")
    }
    constructor(name: String,sex: Char,age:Int,info:String):this(name){
        println("3个参数的次构造函数:name=$name,sex=$sex,age=$age,info=$info")
    }
}

fun main() {
    //调用主构造
    TestBase3("java")
    //调用次构造
    TestBase3("kotlin",'m')
    TestBase3("kotlin",'m',25)
    TestBase3("kotlin",'m',25,"我是语言")

}

执行结果
在这里插入图片描述

4.构造调用顺序

//第一步,生成主构造中的定义的变量
class Test60(name:String,_sex:Char,val age:Int){//主构造

    //第二步,生成 var sex  在init{}前面写
    var sex=_sex
init{
    //第三步走init{}
    println("主构造调用$name,$sex,$age")

}
    constructor(name: String):this(name,'m',25){
        //第五步 调用次构造
        println("次构造调用")
    }

    //第四步
    val dex="kotlin"
}

fun main() {
    println()
    Test59("java") //调用次构造
}   

陷阱1:主构造中的变量赋值和init是同时的 看谁在前面
这么写会报错

class Test63(name : String){ //临时变量
   
    init {
       this.name=name
    }
    var name="java"
}

在这里插入图片描述

根据调用顺序,此时先执行init但是,name是临时变量,不能使用。
正确修改

class Test63(name : String){ //临时变量
    var name="java"
    init {
       this.name=name
    }
   
}

在这里插入图片描述
陷阱2:

class Test63{ 
   val info:String
    init {
        getInfo()
        info="java"
    }

     fun getInfo() {
       println("info=${info[0]}")
    }
}

fun main() {
    Test63().getInfo()
}

执行结果
在这里插入图片描述
上述执行顺序为:Test63()主构造调用–>val info–>init(里面先调用了getInfo(),此时init还未初始化,因此空指针)
正确修改
在这里插入图片描述
陷阱3:

class Test63A(_info : String){
    val concent=getInfoText()
    val info=_info
    fun getInfoText()=info
}


fun main() {
    Test63A("java").concent.length
}

在这里插入图片描述

该调用顺序:主构造-concent-getInfoText(此时info还没接收_info) 所以空指针

最好是将接收的临时变量写到最上面
修改后:
在这里插入图片描述

5.构造函数默认参数

如果用户不传入参数,可以直接使用默认值

package Kotlin.Stage4

class TestBase4(name:String="java"){ //主构造
    //次构造函数必须调用主构造,否在会报错。主构造统一管理,为了更好的初始化
    //2个参数的次构造
    constructor(name: String="kotlin",sex:Char='w'):this(name){
        println("2个参数的次构造函数:name=$name,sex=$sex")
    }
    constructor(name: String="c",sex: Char='m',age:Int=25):this(name){
        println("3个参数的次构造函数:name=$name,sex=$sex,age=$age")
    }
    constructor(name: String="c++",sex: Char='m',age:Int=35,info:String="我是语言"):this(name){
        println("3个参数的次构造函数:name=$name,sex=$sex,age=$age,info=$info")
    }
    fun show(){
        println("主构造函数调用结果")
    }
}

fun main() {
    //调用主构造
    TestBase4("java")
    //调用次构造
    TestBase4("kotlin",'m')
    TestBase4("kotlin",'m',25)
    TestBase4("kotlin",'m',25,"我是语言")
    //上述传入参数会覆盖默认参数
    
    TestBase4().show() //此种情况下会优先调用主构造
}

执行结果
在这里插入图片描述

6.延迟初始化lateinit

1.关键字:lateinit var
2. lateinit val AAA //不能使用val定义,因为不可修改,无法初始化
3.lateinit作用就是先不赋值,等用到的时候在进行赋值,需要给定一个初始化的函数,供调用,kotlin中不给默认值会报错
在这里插入图片描述

4.在调用时必须先初始化 不然会报错

package Kotlin.Stage4

class Test61{
    //lateinit val AAA  //不能使用val定义,因为不可修改,无法初始化
    lateinit var responseResult:String //先不赋值,等用到的时候在进行赋值
    //模拟加载
    fun loadRequest(){
        responseResult="加载成功"  //延时初始化
    }

    fun showResponseResult(){
    //如果没有初始化,用到他时就会报错
        if (responseResult==null){
            println("显示结果")
        }
        println("显示结果$responseResult")
    }
}

fun main() {
    val p=Test61()
    p.showResponseResult()
}

执行结果
在这里插入图片描述
上述报错原因是使用他之前没有调用初始化化的函数,被lateinit var的变量必须调用初始化才能用。
正确修改:


package Kotlin.Stage4

class Test61{
    //lateinit val AAA  //不能使用val定义,因为不可修改,无法初始化
    lateinit var responseResult:String //先不赋值,等用到的时候在进行赋值
    //模拟加载
    fun loadRequest(){
        responseResult="加载成功"  //延时初始化
    }

    fun showResponseResult(){
        //如果没有初始化,用到他时就会报错
        if (responseResult==null){
            println("显示结果")
        }
        println("显示结果$responseResult")
    }
}

fun main() {
    val p=Test61()
    //使用前,先加载(用到他时在调用加载,属于懒加载)
    p.loadRequest()
    p.showResponseResult()
}

执行结果
在这里插入图片描述
5.使用::responseResult.isInitialized的情况下,用到他时不会报错,会判断是否进行了初始化

class Test61{
    //lateinit val AAA  //不能使用val定义,因为不可修改,无法初始化
    lateinit var responseResult:String //先不赋值,等用到的时候在进行赋值
    //模拟加载
    fun loadRequest(){
        responseResult="加载成功"  //延时初始化
    }

    fun showResponseResult(){
       /* //如果没有初始化,用到他时就会报错
        if (responseResult==null){
            println("显示结果")
        }
        println("显示结果$responseResult")*/
        if(::responseResult.isInitialized){
            println("已经初始化")
        }else{
            println("未初始化")
        }


    }
}

fun main() {
    val p=Test61()
    //使用前,先加载(用到他时在调用加载,属于懒加载)
    //p.loadRequest()
    p.showResponseResult()
}

执行结果
在这里插入图片描述

7.惰性初始化

lateinit在加载时需要手动调用,然后在使用  by lazy直接可以使用
package Kotlin.Stage4

class Test62{
    //lateinit val AAA  //不能使用val定义,因为不可修改,无法初始化
    val responseResult by lazy {loadRequest()}
    //模拟加载
    fun loadRequest():String{
        println("正在加载中...")
      return "加载成功"

    }

    fun showResponseResult(){
        println("显示结果:$responseResult")


    }
}

fun main() {
    val p=Test62()
    p.showResponseResult()
}

执行结果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值