Kotlin 中有两种构造器:主构造器和次构造器。都用关键字 constructor
来表示。但是在每个类中,主构造器有且仅有一个(如果没有定义,则编译器会自动提供一个空构造器),而次构造器可以有
0 个或多个。
主构造器声明
主构造器声明在类名后面,每个类有且仅有一个。
空参/有参主构造器
1 2 3 4 5 6 7 8 9 10 11 12 13
| class People constructor() { var name: String? = null var age: Int = 10 lateinit var cards: MutableList<Card> }
class People constructor(name: String, age: Int) { var name: String? = null var age: Int = 10 lateinit var cards: MutableList<Card> }
|
主构造器的 constructor 关键字可以省略
1 2 3 4 5 6 7 8 9 10 11 12 13
| class People() { var name: String? = null var age: Int = 10 lateinit var cards: MutableList<Card> }
class People(name: String?, age: Int) { var name: String? = null var age: Int = 10 lateinit var cards: MutableList<Card> }
|
当然,如果需要加权限修饰符,那么就不能省略 constructor
关键字了,而且该权限修饰符在 constructor 关键字前面。
1 2 3 4 5 6 7 8 9 10 11 12 13
| class People private constructor() { var name: String? = null var age: Int = 10 lateinit var cards: MutableList<Card> }
class People private constructor(name: String?, age: Int) { var name: String? = null var age: Int = 10 lateinit var cards: MutableList<Card> }
|
init
代码块
Kotlin的主构造器是没有方法体的,这就意味着我们无法在主构造器中进行任何操作。
但 Kotlin 为我们提供了一个 init
代码块,这个代码块的执行顺序在主构造方法之后,次构造方法之前,我们可以在这个代码块中进行各种初始化的操作,包括访问主构造方法中的参数。
1 2 3 4 5 6 7 8 9 10
| class People(name: String?, age: Int) { var name: String? = null var age: Int = 10 lateinit var cards: MutableList<Card> init { this.name = name this.age = age } }
|
可以看到在这里,init 代码块将属性 name 和 age
初始化了。但是,这样类似 Java 的做法看起来非常繁琐,Kotlin
提供了一个比较简洁的方法,即在主构造器中声明属性。下面的写法与上面的完全等价。
1 2 3
| class People(var name: String? = null, var age: Int = 10) { lateinit var cards: MutableList<Card> }
|
当然,主构造器中声明的属性也可以加上权限修饰符。
1 2 3
| class People(private var name: String? = null, private var age: Int = 10) { lateinit var cards: MutableList<Card> }
|
次构造器声明
次构造器声明在类内,每个类可以有 0 个或多个。
空参/有参次构造器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class People { var name: String? = null var age: Int = 10 lateinit var Cards: MutableList<Card>
constructor() {}
constructor(name: String?, age: Int) { this.name = name this.age = age }
private constructor(name: String?, age: Int, cards: MutableList<Card>) { this.name = name this.age = age this.cards = cards } }
|
没有主构造器时,次构造器就代替了主构造器的作用。(但是其实仍然调用了空的主构造器)
当主构造器和次构造器同时存在时,次构造器必须直接或者间接调用主构造器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class People(name: String?) { var name: String? = null var age: Int = 10 lateinit var cards: MutableList<Card>
constructor() : this("你好", 100)
constructor(name: String?, age: Int) : this(name) { this.name = name this.age = age } }
|
可以看到,在执行顺序上,主构造器 > init代码块 >
次构造器