kotlin的构造方法

发布时间 2023-10-18 00:20:28作者: LCAC

一、构造方法的组成

1、主构造方法

class View(tt: Int) {.....}
class View constructor(tt: Int) {....}

如上所示有两种方式,且都是在类体外的括号中

第二种方式增加了constructor,正常情况下constructor是可以省略,除非有需要给主构造函数设置可见性或者注解如下所示:

class View private constructor(tt: Int) {....} // 主构造函数设置为私有的,则外部不能通过主构造函数进行创建该类;通常用于单例

class View @Inject constructor(tt: Int) {....} // 这里增加这个Inject注解来标记一个需要注入的依赖项

 

2、初始化语句块

一个类里面可以有多个初始化语句块,格式是 init {......}

class View(tt: Int) {
    init { // 这个init会先执行,然后再执行下面的init
        println("view init: ${tt}")
    }
    init {
        println("view init 2")
    }
}

如果有多个init,则会从上到下按顺序执行

3、从构造方法

一个类里面可以有多个从构造方法,格式是 constructor(.....): this(...)或者如果有父类可以是 constructor(.....): super(...) 

open class View {
    constructor(ctx: String): this(ctx, "attr?") { // 这里的this调用的是下面的构造方法
        println("constructor(ctx: String):${ctx}")
    }
    constructor(ctx: String, attr: String) {
        println("constructor(ctx: String, attr: String): ${ctx}, ${attr}")
    }
}

下面是继承View的构造函数

class Mybutton: View {
    constructor(ctx: String): this(ctx, "default") {} //调用下面的构造函数
    constructor(ctx: String, attr: String): super("kkqqq") {} // 调用父类的View的构造函数
}

 

二、主构造、从构造和init的调用顺序

1、有冒号先调用冒号右边的

2、init比构造函数先调用

open class View {
    init {
        println("view 1")
    }
    init {
        println("view 2")
    }
    constructor(ctx: String): this(ctx, "attr?") {
        println("view 3")
    }
    constructor(ctx: String, attr: String) {
        println("view 4")
    }
}
class Mybutton: View {
    init {
        println("Mybutton0")
    }
    constructor(ctx: String): this(ctx, "default") {
        println("Mybutton1")
    }
    constructor(ctx: String, attr: String): super("kkqqq") {
        println("Mybutton2")
    }
}

val button1 = Mybutton("ctx")

// 打印的结果是
/*
view 1
view 2
view 4
view 3
Mybutton0
Mybutton2
Mybutton1
*/

先是父类的init,并且init从上到下的顺序;最后才是子类:子类的init,然后才是子类的构造函数

 

三、主构造函数和从构造函数的关系

1、从构造函数最终一定要去调用主构造函数

open class View(v: Int) {
    constructor(ctx: String): this(ctx, "attr?") { // 这里继续调用下面的从构造函数
        println("view 3")
    }
    constructor(ctx: String, attr: String): this(5) { // 因为有主构造函数,并且这里没有继续调用从构造函数,所以必须去调用主构造函数
        println("view 4")
    }
}

2、子类没有主构造函数时候,不能在主构造函数继承的父类进行初始化

class Mybutton: View("view") // 这样子是不被允许的,Mybutton没有主构造函数,View不能在主构造函数的位置进行初始化
class Mybutton(): View("view") // 这里Mybutton有主构造函数,虽然没有参数

3、子类在构造函数的最后一定要去初始化父类,不管是在主构造函数还是从构造函数中,至少要有一个地方要去初始化