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