Kotlin - 构造函数 constructor

一、概念
构造函数分为 主构造函数 和 次构造函数。主构造只有一个,次构造可以有多个。
不声明任何构造时,Kotlin会给默认增加一个空参主构造。如果不希望外部创建实例,可以声明有参的主构造或次构造,或者非默认public的空参主构造或空参次构造。
执行顺序:主构造 > init代码块 > 次构造
二、主构造函数
有可见性修饰或注解的时候,constructor 不能省略。

//构造有可见性修饰或注解的时候,关键字不能省略
class Demo private @Inject constructor() {}
//推荐下面写法(定义无参主构造,写次构造需要每次都委托)
class Demo() {}
//主构造无参数可以省略括号(未定义次构造时,类默认提供一个无参主构造)
class Demo {}
//无类体可以省略大括号
class Demo


主构造中参数的使用:

使用var、val修饰,会自动声明并初始化同名成员属性。(推荐,其实就是自动使用了init{ } )
手动使用 init{} 代码块手动声明并初始化。可以存在多个 init{} 代码块,执行顺序和声明顺序一致。

//方式一:使用var、val自动声明初始化
class Demo(var id: Int, var name: String) {
    //实在需要也可以再写init{}代码块做一些逻辑
    init{
        println("$id 、 $name")
    }
}
 
//方式二:使用init{}代码块手动声明初始化
//id、name只能在构造和成员属性中调用,可以声明同名成员属性,无法在成员函数中调用
class Demo(id: Int, name: String) {
    var id? = null
    var name? = ""
    init {
        this.id = id
        this.name = name
    }
}


三、次构造函数
次构造不能像主构造那样使用val/var,只能手动声明并初始化成员属性,由于次构造会改变成员属性的值,因此该成员属性只能手动声明为var。
有声明主构造时,次构造必须使用委托的方式直接或间接调用主构造。​​​​
3.1 未声明主构造的情况
写法和Java类似。次构造不能委托给主构造,因为没有主构造。

class Demo {
    var id: Long? = null
    var name: String? = null
    var age: Int? = null
 
    constructor(){}
    constructor(id: Long) {
        this.id = id
    }
    constructor(name: String, age: Int) {
        this.name = name
        this.age = age
    }
}
 
var aa = Demo()
var bb = Demo(222)
var cc = Demo("张三",18)

3.2 声明空参主构造的情况
次构造使用委托调用主构造。

//有空参主构造的情况下,定义空参次构造报错重载冲突,若委托给空参this()报错调用链无限循环
//使用委托的方式调用主构造

class Demo() {
    var id: Long? = null
    var name: String? = null
    var age: Int? = null
 
    constructor(id: Long) : this() {
        this.id = id
    }
    constructor( name: String, age: Int) : this() {
        this.name = name
        this.age = age
    }
}
 
var aa = Demo()
var bb = Demo(222)
var cc = Demo("张三",18)

 3.3 声明有参主构造的情况
主构造使用默认参数简化次构造重载。

//主构造中的形参id未提供默认值,因此不能创建空参实例
//即便id提供默认值了,声明空参次构造委托空参this()报错调用链无限循环
//但可以委托有参数 this(10086) 或 this(name = ""),相当于调用了主构造
class Demo(var id: Long, var name: String = "", var age: Int = 0) {
    var sex: Boolean? = null
 
    //这样可以声明空参构造,也就可以创建空参实例了
    constructor() : this(10086) {}
 
    //主构造未包含字段sex,声明一个次构造来使用它,依然使用委托来调用主构造
    //不管次构造中有多少Long类型参数,往this()里面传一个进去就行
    //往this()里面传参要按照参数列表顺序,因为主构造里有默认参数,可以使用命名参数的形式部分传参
    constructor(sex: Boolean, aa: Long, bb: Long, cc: String) : this(bb) {
        this.sex = sex
        //主构造使用var/val后就默认有了name属性可以使用,不用再手动声明并初始化
        //cc可以传递进this()中,就不用在这里手动赋值name了
        this.name = cc
    }
}
 
var aa = Demo(10086, "张三")
var bb = Demo(10086, age = 18)  //不使用命名参数,第二个得传name
var cc = Demo(false,10086,10010,"张三")

3.4 次构造之间相互调用的情况
也使用委托简化。

//Java
class Demo {
    public Demo(long id) {
        this.id = id;
    }
    public Demo(String name) {
        this(name.hashCode());    //使用this()访问重载的构造
        this.name = name;
    }
}
 
//Kotlin 无主构造的情况,写法和Java类似
class Demo{
    constructor(id:Long){
        this.id = id
    }
    constructor(name:String):this(name.hashCode().toLong()){
        this.name = name
    }
}
 
//Kotlin 有主构造的情况
class Demo(val id: Long) {
    //直接调用主构造
    constructor(name: String) : this(name.hashCode().toLong()) {
        this.name = name
    }
    //调用了上面的构造,间接调用主构造
    constructor(name: String, sex: Boolean) : this(name) {
        this.sex = sex
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值