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 // 这是本类的最终构造函数 } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!