kotlin的构造方法

一、构造方法的组成

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、子类在构造函数的最后一定要去初始化父类,不管是在主构造函数还是从构造函数中,至少要有一个地方要去初始化

 

四、类属性的初始化

1、直接定义在主构造函数中

class View(val mvar: Int)  // 这里对mvar使用val或者var表明是View中的属性

 

2、在声明的时候,直接初始化或者从主构造函数中获取对应的值

open class View(val v: Int) {
    open val mvar: Int = v // 这个v为主构造函数中的参数, 或者直接初始化 val mvar: Int = 10
}

 

3、声明在init之前,然后在init中进行初始化

open class View(val v: Int) {
    open val mvar: Int
    init {
        mvar = v // 在init位置进行初始化,初始化的值同2
    }

 

4、在没有主构造函数时候,从构造函数是出口(没有冒号,或者冒号右边是父类)的函数中进行初始化

复制代码
class Mybutton: View {
    override val mvar: Int
    constructor(ctx: String): this(ctx, "default") {
        // mvar = 20 // 不能在这里初始化,应为冒号右边继续调用本类的构造函数,不是最终的构造函数
        
    }
    constructor(ctx: String, attr: String): super("kkqqq") {
        mvar = 20 // 这是本类的最终构造函数
    }
}
复制代码

 

posted @   LCAC  阅读(742)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
点击右上角即可分享
微信分享提示